11/9/1
This commit is contained in:
@@ -3,6 +3,7 @@ import 'dart:io';
|
||||
|
||||
import 'package:SEFER/constant/info.dart';
|
||||
import 'package:SEFER/controller/firebase/firbase_messge.dart';
|
||||
import 'package:SEFER/controller/functions/add_error.dart';
|
||||
import 'package:SEFER/views/auth/login_page.dart';
|
||||
import 'package:SEFER/views/auth/sms_verfy_page.dart';
|
||||
import 'package:SEFER/views/widgets/my_dialog.dart';
|
||||
@@ -15,6 +16,7 @@ import 'package:SEFER/main.dart';
|
||||
import 'package:SEFER/views/home/map_page_passenger.dart';
|
||||
import 'package:location/location.dart';
|
||||
|
||||
import '../../print.dart';
|
||||
import '../functions/package_info.dart';
|
||||
|
||||
class LoginController extends GetxController {
|
||||
@@ -90,23 +92,22 @@ class LoginController extends GetxController {
|
||||
} else {
|
||||
var jsonDecoeded = jsonDecode(res);
|
||||
if (jsonDecoeded.isNotEmpty) {
|
||||
var d = jsonDecoeded['data'][0];
|
||||
if (jsonDecoeded['status'] == 'success' &&
|
||||
jsonDecoeded['data'][0]['verified'].toString() == '1') {
|
||||
d['verified'].toString() == '1') {
|
||||
//
|
||||
|
||||
box.write(BoxName.isVerified, '1');
|
||||
box.write(BoxName.email, jsonDecoeded['data'][0]['email']);
|
||||
box.write(BoxName.phone, jsonDecoeded['data'][0]['phone']);
|
||||
box.write(BoxName.email, d['email']);
|
||||
box.write(BoxName.phone, d['phone']);
|
||||
box.write(BoxName.isTest, '1');
|
||||
box.write(BoxName.package, jsonDecoeded['data'][0]['package']);
|
||||
box.write(BoxName.promo, jsonDecoeded['data'][0]['promo']);
|
||||
box.write(BoxName.discount, jsonDecoeded['data'][0]['discount']);
|
||||
box.write(BoxName.validity, jsonDecoeded['data'][0]['validity']);
|
||||
box.write(BoxName.isInstall,
|
||||
jsonDecoeded['data'][0]['isInstall'] ?? 'none');
|
||||
box.write(BoxName.isGiftToken,
|
||||
jsonDecoeded['data'][0]['isGiftToken'] ?? 'none');
|
||||
box.write(BoxName.inviteCode,
|
||||
jsonDecoeded['data'][0]['inviteCode'] ?? 'none');
|
||||
box.write(BoxName.package, d['package']);
|
||||
box.write(BoxName.promo, d['promo']);
|
||||
box.write(BoxName.discount, d['discount']);
|
||||
box.write(BoxName.validity, d['validity']);
|
||||
box.write(BoxName.isInstall, d['isInstall'] ?? 'none');
|
||||
box.write(BoxName.isGiftToken, d['isGiftToken'] ?? 'none');
|
||||
box.write(BoxName.inviteCode, d['inviteCode'] ?? 'none');
|
||||
|
||||
var token = await CRUD().get(link: AppLink.getTokens, payload: {
|
||||
'passengerID': box.read(BoxName.passengerID).toString()
|
||||
@@ -114,11 +115,11 @@ class LoginController extends GetxController {
|
||||
if (token != 'failure') {
|
||||
if (jsonDecode(token)['data'][0]['token'] !=
|
||||
box.read(BoxName.tokenFCM)) {
|
||||
Get.put(FirebaseMessagesController())
|
||||
.sendNotificationToAnyWithoutData(
|
||||
Get.put(FirebaseMessagesController()).sendNotificationToDriverMAP(
|
||||
'token change'.tr,
|
||||
'change device'.tr,
|
||||
jsonDecode(token)['data'][0]['token'].toString(),
|
||||
[],
|
||||
'cancel.wav',
|
||||
);
|
||||
Future.delayed(const Duration(seconds: 1));
|
||||
@@ -153,10 +154,10 @@ class LoginController extends GetxController {
|
||||
Get.offAll(() => const MapPagePassenger());
|
||||
},
|
||||
);
|
||||
} else {
|
||||
print('same');
|
||||
}
|
||||
} // Logging to check if inviteCode is written correctly
|
||||
print("Invite Code in Box: ${box.read(BoxName.inviteCode)}");
|
||||
print("Is Install: ${box.read(BoxName.isInstall)}");
|
||||
|
||||
if (box.read(BoxName.inviteCode).toString() != 'none' &&
|
||||
box.read(BoxName.isInstall).toString() != '1') {
|
||||
@@ -171,15 +172,22 @@ class LoginController extends GetxController {
|
||||
middleText: "Your invite code was successfully applied!"
|
||||
.tr, // Automatically translates based on the current locale
|
||||
onConfirm: () {
|
||||
CRUD().post(link: AppLink.addPassengersPromo, payload: {
|
||||
"promoCode":
|
||||
'S-${box.read(BoxName.name).toString().split(' ')[0]}',
|
||||
"amount": '25',
|
||||
"passengerID": box.read(BoxName.passengerID).toString(),
|
||||
"description": 'promo first'
|
||||
});
|
||||
Get.offAll(() =>
|
||||
const MapPagePassenger()); // Navigate to MapPagePassenger after confirmation
|
||||
try {
|
||||
CRUD().post(link: AppLink.addPassengersPromo, payload: {
|
||||
"promoCode":
|
||||
'S-${box.read(BoxName.name).toString().split(' ')[0]}',
|
||||
"amount": '25',
|
||||
"passengerID": box.read(BoxName.passengerID).toString(),
|
||||
"description": 'promo first'
|
||||
});
|
||||
} catch (e) {
|
||||
addError(e.toString(),
|
||||
'passenger Invitation Used dialogu as promo line 185 login_controller');
|
||||
} finally {
|
||||
// Continue with the rest of your flow, regardless of errors
|
||||
// For example, navigate to the next page
|
||||
Get.offAll(() => const MapPagePassenger());
|
||||
}
|
||||
},
|
||||
textConfirm: "OK".tr, // Confirm button text
|
||||
);
|
||||
@@ -200,34 +208,6 @@ class LoginController extends GetxController {
|
||||
}
|
||||
}
|
||||
|
||||
// void adminDashboardOpen() async {
|
||||
// if (formKeyAdmin.currentState!.validate()) {
|
||||
// await DeviceInfoPlus.getDeviceInfo();
|
||||
// if (Platform.isAndroid) {
|
||||
// // var res = await CRUD().get(link: AppLink.getAdminUser, payload: {
|
||||
// // // 'device_number': DeviceInfoPlus.deviceData['serialNumber'].toString(),
|
||||
// // });
|
||||
// // var d = jsonDecode(res);
|
||||
// // // if (DeviceInfoPlus.deviceData['serialNumber'] ==
|
||||
// // d['message']['device_number']) {
|
||||
// Get.back();
|
||||
// Get.to(() => const AdminHomePage());
|
||||
// // }
|
||||
// }
|
||||
// if (Platform.isIOS) {
|
||||
// // var res = await CRUD().get(link: AppLink.getAdminUser, payload: {
|
||||
// // 'device_number': DeviceInfoPlus.deviceData['identifierForVendor'].toString(),
|
||||
// // });
|
||||
// // var d = jsonDecode(res);
|
||||
// // if (DeviceInfoPlus.deviceData['serialNumber'] ==
|
||||
// // d['message']['device_number']) {
|
||||
// Get.back();
|
||||
// Get.to(() => const AdminHomePage());
|
||||
// // }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
void login() async {
|
||||
isloading = true;
|
||||
update();
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'dart:math';
|
||||
|
||||
import 'package:SEFER/constant/colors.dart';
|
||||
import 'package:SEFER/controller/auth/login_controller.dart';
|
||||
import 'package:SEFER/controller/functions/add_error.dart';
|
||||
import 'package:SEFER/controller/local/phone_intel/phone_number.dart';
|
||||
import 'package:SEFER/views/home/map_page_passenger.dart';
|
||||
import 'package:SEFER/views/widgets/my_dialog.dart';
|
||||
@@ -134,66 +135,51 @@ class RegisterController extends GetxController {
|
||||
String phoneNumber = phoneController.text;
|
||||
|
||||
// Check if the phone number is from Egypt (Assuming Egyptian numbers start with +20)
|
||||
bool isEgyptianNumber = phoneNumber.startsWith('+20');
|
||||
// print('dfdf${phoneNumber.toString().split('+2')[1]}');
|
||||
if (isEgyptianNumber && phoneNumber.length == 13) {
|
||||
// Check if the phone number is already verified
|
||||
var responseChecker = await CRUD().post(
|
||||
link: AppLink.checkPhoneNumberISVerfiedPassenger,
|
||||
payload: {
|
||||
'phone_number': phoneNumber,
|
||||
'email': box.read(BoxName.email),
|
||||
},
|
||||
);
|
||||
|
||||
if (responseChecker != 'failure') {
|
||||
var data = jsonDecode(responseChecker);
|
||||
if (phoneController.text.isNotEmpty) {
|
||||
bool isEgyptianNumber = phoneNumber.startsWith('+20');
|
||||
if (isEgyptianNumber && phoneNumber.length == 13) {
|
||||
// Check if the phone number is already verified
|
||||
var responseChecker = await CRUD().post(
|
||||
link: AppLink.checkPhoneNumberISVerfiedPassenger,
|
||||
payload: {
|
||||
'phone_number': phoneNumber,
|
||||
'email': box.read(BoxName.email),
|
||||
},
|
||||
);
|
||||
|
||||
// If the phone number is already verified
|
||||
if (data['message'][0]['verified'].toString() == '1') {
|
||||
Get.snackbar('Phone number is verified before'.tr, '',
|
||||
backgroundColor: AppColor.greenColor);
|
||||
box.write(BoxName.isVerified, '1');
|
||||
box.write(BoxName.phone, phoneNumber);
|
||||
Get.offAll(const MapPagePassenger());
|
||||
if (responseChecker != 'failure') {
|
||||
var data = jsonDecode(responseChecker);
|
||||
|
||||
// If the phone number is already verified
|
||||
if (data['message'][0]['verified'].toString() == '1') {
|
||||
Get.snackbar('Phone number is verified before'.tr, '',
|
||||
backgroundColor: AppColor.greenColor);
|
||||
box.write(BoxName.isVerified, '1');
|
||||
box.write(BoxName.phone, phoneNumber);
|
||||
Get.offAll(const MapPagePassenger());
|
||||
} else {
|
||||
await sendOtp(phoneNumber, randomNumber, isEgyptianNumber,
|
||||
smsEgyptController);
|
||||
}
|
||||
} else {
|
||||
// If the phone number is not verified, send OTP
|
||||
// if (isEgyptianNumber) {
|
||||
// if (isValidEgyptianPhoneNumber(
|
||||
// phoneNumber.toString().split('+2')[1])) {
|
||||
await sendOtp(phoneNumber, randomNumber, isEgyptianNumber,
|
||||
smsEgyptController);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
// If verification check fails, still send OTP
|
||||
// if (isEgyptianNumber) {
|
||||
// if (isValidEgyptianPhoneNumber(
|
||||
// phoneNumber.toString().split('+2')[1])) {
|
||||
await sendOtp(
|
||||
sendOtp(
|
||||
phoneNumber, randomNumber, isEgyptianNumber, smsEgyptController);
|
||||
// } else {
|
||||
// MyDialog().getDialog(
|
||||
// 'Error'.tr, "Phone number isn't an Egyptian phone number".tr,
|
||||
// () {
|
||||
// Get.back();
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
// MyDialog().getDialog(
|
||||
// 'Error'.tr, 'Phone number must be exactly 11 digits long'.tr, () {
|
||||
// Get.back();
|
||||
// });
|
||||
sendOtp(
|
||||
phoneNumber, randomNumber, isEgyptianNumber, smsEgyptController);
|
||||
print(phoneNumber);
|
||||
MyDialog().getDialog(
|
||||
'Error'.tr, 'Phone number must be exactly 11 digits long'.tr, () {
|
||||
Get.back();
|
||||
});
|
||||
// sendOtp(
|
||||
// phoneNumber, randomNumber, isEgyptianNumber, smsEgyptController);
|
||||
}
|
||||
} catch (e) {
|
||||
// Handle error
|
||||
print('Error: $e');
|
||||
} finally {
|
||||
isLoading = false;
|
||||
update();
|
||||
@@ -205,34 +191,14 @@ class RegisterController extends GetxController {
|
||||
SmsEgyptController controller) async {
|
||||
// Trim any leading or trailing whitespace from the phone number
|
||||
phoneNumber = phoneNumber.trim();
|
||||
Log.print('phoneNumber: ${phoneNumber}');
|
||||
|
||||
await CRUD().post(link: AppLink.sendVerifyOtpMessage, payload: {
|
||||
'phone_number': phoneNumber,
|
||||
'token': otp.toString(),
|
||||
});
|
||||
if (isEgyptian) {
|
||||
// // Check if the phone number has exactly 11 digits
|
||||
// if (phoneNumber.length == 11 &&
|
||||
// RegExp(r'^\d{11}$').hasMatch(phoneNumber)) {
|
||||
// Send SMS for Egyptian phone numbers
|
||||
await CRUD().post(link: AppLink.sendVerifyOtpMessage, payload: {
|
||||
'phone_number': phoneNumber,
|
||||
'token': otp.toString(),
|
||||
// 'urlImage': box.read(BoxName.passengerPhotoUrl),
|
||||
// 'name': box.read(BoxName.name),
|
||||
});
|
||||
|
||||
await controller.sendSmsEgypt(phoneNumber, otp.toString());
|
||||
print('SMS sent to Egyptian phone number: $phoneNumber');
|
||||
} else {
|
||||
// // Show error dialog if phone number is invalid
|
||||
// MyDialog().getDialog('Invalid Phone Number',
|
||||
// 'The phone number must be exactly 11 digits long.', () {
|
||||
// Get.back();
|
||||
// });
|
||||
// }
|
||||
|
||||
// else {
|
||||
// Send WhatsApp message for non-Egyptian phone numbers
|
||||
await CRUD().sendWhatsAppAuth(phoneNumber, otp.toString());
|
||||
print('WhatsApp message sent to non-Egyptian phone number: $phoneNumber');
|
||||
}
|
||||
isLoading = false;
|
||||
|
||||
@@ -243,98 +209,72 @@ class RegisterController extends GetxController {
|
||||
}
|
||||
|
||||
verifySMSCode() async {
|
||||
// if (formKey3.currentState!.validate()) {
|
||||
Log.print('phoneController.text: ${phoneController.text}');
|
||||
// if (isValidEgyptianPhoneNumber(phoneController.text)) {
|
||||
var res = await CRUD().post(link: AppLink.verifyOtpMessage, payload: {
|
||||
'phone_number': phoneController.text,
|
||||
'token': verifyCode.text.toString(),
|
||||
});
|
||||
if (res != 'failure') {
|
||||
// var dec = jsonDecode(res);
|
||||
box.write(BoxName.phoneDriver, phoneController.text);
|
||||
var payload = {
|
||||
'id': box.read(BoxName.passengerID),
|
||||
'phone': phoneController.text,
|
||||
'email': box.read(BoxName.email),
|
||||
'password': 'unknown',
|
||||
'gender': 'unknown',
|
||||
'birthdate': '2002-01-01',
|
||||
'site': box.read(BoxName.passengerPhotoUrl) ?? 'unknown',
|
||||
'first_name': box.read(BoxName.name).toString().split(' ')[0],
|
||||
'last_name': box.read(BoxName.name).toString().split(' ')[1],
|
||||
};
|
||||
try {
|
||||
if (formKey3.currentState!.validate()) {
|
||||
var res = await CRUD().post(link: AppLink.verifyOtpMessage, payload: {
|
||||
'phone_number': phoneController.text,
|
||||
'token': verifyCode.text.toString(),
|
||||
});
|
||||
|
||||
var res1 = await CRUD().post(
|
||||
link: AppLink.signUp,
|
||||
payload: payload,
|
||||
);
|
||||
if (res1 != 'failure') {
|
||||
CRUD().post(
|
||||
link: '${AppLink.seferAlexandriaServer}/auth/signup.php',
|
||||
payload: payload,
|
||||
);
|
||||
CRUD().post(
|
||||
link: '${AppLink.seferGizaServer}/auth/signup.php',
|
||||
payload: payload,
|
||||
);
|
||||
box.write(BoxName.isVerified, '1');
|
||||
box.write(BoxName.isFirstTime, '0');
|
||||
box.write(BoxName.phone, phoneController.text);
|
||||
// Get.offAll(const MapPagePassenger());
|
||||
Get.put(LoginController()).loginUsingCredentials(
|
||||
box.read(BoxName.passengerID).toString(),
|
||||
box.read(BoxName.email).toString(),
|
||||
);
|
||||
if (res != 'failure') {
|
||||
box.write(BoxName.phoneDriver, phoneController.text);
|
||||
var nameParts = box.read(BoxName.name).toString().split(' ');
|
||||
var firstName = nameParts.isNotEmpty ? nameParts[0] : 'unknown';
|
||||
var lastName = nameParts.length > 1 ? nameParts[1] : 'unknown';
|
||||
|
||||
var payload = {
|
||||
'id': box.read(BoxName.passengerID),
|
||||
'phone': phoneController.text,
|
||||
'email': box.read(BoxName.email),
|
||||
'password': 'unknown',
|
||||
'gender': 'unknown',
|
||||
'birthdate': '2002-01-01',
|
||||
'site': box.read(BoxName.passengerPhotoUrl) ?? 'unknown',
|
||||
'first_name': firstName,
|
||||
'last_name': lastName,
|
||||
};
|
||||
|
||||
var res1 = await CRUD().post(
|
||||
link: AppLink.signUp,
|
||||
payload: payload,
|
||||
);
|
||||
|
||||
if (res1 != 'failure') {
|
||||
await CRUD().post(
|
||||
link: '${AppLink.seferAlexandriaServer}/auth/signup.php',
|
||||
payload: payload,
|
||||
);
|
||||
await CRUD().post(
|
||||
link: '${AppLink.seferGizaServer}/auth/signup.php',
|
||||
payload: payload,
|
||||
);
|
||||
|
||||
box.write(BoxName.isVerified, '1');
|
||||
box.write(BoxName.isFirstTime, '0');
|
||||
box.write(BoxName.phone, phoneController.text);
|
||||
|
||||
Get.put(LoginController()).loginUsingCredentials(
|
||||
box.read(BoxName.passengerID).toString(),
|
||||
box.read(BoxName.email).toString(),
|
||||
);
|
||||
} else {
|
||||
Get.snackbar('Error'.tr,
|
||||
"The email or phone number is already registered.".tr,
|
||||
backgroundColor: Colors.redAccent);
|
||||
}
|
||||
} else {
|
||||
Get.snackbar('Error'.tr, "phone not verified".tr,
|
||||
backgroundColor: Colors.redAccent);
|
||||
}
|
||||
} else {
|
||||
Get.snackbar('Error'.tr, "you must insert token code".tr,
|
||||
backgroundColor: AppColor.redColor);
|
||||
}
|
||||
} else {
|
||||
Get.snackbar(
|
||||
'Error'.tr, "The email or phone number is already registered.".tr,
|
||||
} catch (e) {
|
||||
addError(e.toString(), 'passenger sign up ');
|
||||
Get.snackbar('Error'.tr, "Something went wrong. Please try again.".tr,
|
||||
backgroundColor: Colors.redAccent);
|
||||
}
|
||||
// } else {
|
||||
// var res = await CRUD().post(link: AppLink.verifyOtpMessage, payload: {
|
||||
// 'phone_number': phoneController.text,
|
||||
// 'token': verifyCode.text.toString(),
|
||||
// });
|
||||
// if (res != 'failure') {
|
||||
// // var dec = jsonDecode(res);
|
||||
// box.write(BoxName.phoneDriver, '+${phoneController.text}');
|
||||
// var payload = {
|
||||
// 'id': box.read(BoxName.passengerID),
|
||||
// 'phone': phoneController.text,
|
||||
// 'email': box.read(BoxName.email),
|
||||
// 'password': 'unknown',
|
||||
// 'gender': 'unknown',
|
||||
// 'birthdate': '2002-01-01',
|
||||
// 'site': 'unknown',
|
||||
// 'first_name': box.read(BoxName.name).toString().split(' ')[0],
|
||||
// 'last_name': box.read(BoxName.name).toString().split(' ')[1],
|
||||
// };
|
||||
|
||||
// var res1 = await CRUD().post(
|
||||
// link: AppLink.signUp,
|
||||
// payload: payload,
|
||||
// );
|
||||
// if (res1 != 'failure') {
|
||||
// CRUD().post(
|
||||
// link: '${AppLink.seferAlexandriaServer}/auth/signup.php',
|
||||
// payload: payload,
|
||||
// );
|
||||
// CRUD().post(
|
||||
// link: '${AppLink.seferGizaServer}/auth/signup.php',
|
||||
// payload: payload,
|
||||
// );
|
||||
// box.write(BoxName.isVerified, '1');
|
||||
// box.write(BoxName.phone, '+${phoneController.text}');
|
||||
// Get.offAll(const MapPagePassenger());
|
||||
// }
|
||||
// } else {
|
||||
// Get.snackbar(
|
||||
// 'Error'.tr, "The email or phone number is already registered.".tr,
|
||||
// backgroundColor: Colors.redAccent);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
sendVerifications() async {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:SEFER/views/widgets/my_dialog.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -65,6 +66,9 @@ class FirebaseMessagesController extends GetxController {
|
||||
}
|
||||
}
|
||||
|
||||
NotificationController notificationController =
|
||||
Get.find<NotificationController>();
|
||||
|
||||
Future getTokens() async {
|
||||
String? basicAuthCredentials =
|
||||
await storage.read(key: BoxName.basicAuthCredentials);
|
||||
@@ -118,6 +122,10 @@ class FirebaseMessagesController extends GetxController {
|
||||
|
||||
void fireBaseTitles(RemoteMessage message) {
|
||||
if (message.notification!.title! == 'Order'.tr) {
|
||||
if (Platform.isAndroid) {
|
||||
notificationController.showNotification(
|
||||
'Order', message.notification!.body!, 'Order');
|
||||
}
|
||||
} else if (message.notification!.title! == 'Apply Ride'.tr) {
|
||||
var passengerList = message.data['passengerList'];
|
||||
|
||||
@@ -128,20 +136,22 @@ class FirebaseMessagesController extends GetxController {
|
||||
Get.find<MapPassengerController>().isSearchingWindow == false;
|
||||
Get.find<MapPassengerController>().update();
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController().showNotification(
|
||||
notificationController.showNotification(
|
||||
'Apply Order'.tr, 'Driver Applied the Ride for You'.tr, 'order1');
|
||||
//notificationController.showNotification(
|
||||
// 'Apply Order'.tr, 'Driver Applied the Ride for You'.tr, 'order1');
|
||||
}
|
||||
// driverAppliedTripSnakBar();
|
||||
} else if (message.notification!.title! == 'Promo'.tr) {
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController()
|
||||
.showNotification('Promo', 'Show latest promo'.tr, 'promo');
|
||||
notificationController.showNotification(
|
||||
'Promo', 'Show latest promo'.tr, 'promo');
|
||||
}
|
||||
Get.to(const PromosPassengerPage());
|
||||
} else if (message.notification!.title! == 'Trip Monitoring'.tr) {
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController()
|
||||
.showNotification('Trip Monitoring'.tr, '', 'iphone_ringtone');
|
||||
notificationController.showNotification(
|
||||
'Trip Monitoring'.tr, '', 'iphone_ringtone');
|
||||
}
|
||||
var myListString = message.data['passengerList'];
|
||||
var myList = jsonDecode(myListString) as List<dynamic>;
|
||||
@@ -151,65 +161,67 @@ class FirebaseMessagesController extends GetxController {
|
||||
});
|
||||
} else if (message.notification!.title! == 'token change'.tr) {
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController()
|
||||
.showNotification('token change'.tr, 'token change'.tr, 'cancel');
|
||||
notificationController.showNotification(
|
||||
'token change'.tr, 'token change'.tr, 'cancel');
|
||||
}
|
||||
GoogleSignInHelper.signOut();
|
||||
} else if (message.notification!.title! == 'DriverIsGoingToPassenger'.tr) {
|
||||
Get.find<MapPassengerController>().isDriverInPassengerWay = true;
|
||||
Get.find<MapPassengerController>().update();
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController().showNotification('Driver is Going To You'.tr,
|
||||
notificationController.showNotification('Driver is Going To You'.tr,
|
||||
'Please stay on the picked point.'.tr, 'tone1');
|
||||
}
|
||||
// Get.snackbar('Driver is Going To Passenger', '',
|
||||
// backgroundColor: AppColor.greenColor);
|
||||
} else if (message.notification!.title! == 'message From passenger') {
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController()
|
||||
.showNotification('message From passenger'.tr, ''.tr, 'tone2');
|
||||
notificationController.showNotification(
|
||||
'message From passenger'.tr, ''.tr, 'tone2');
|
||||
}
|
||||
passengerDialog(message.notification!.body!);
|
||||
|
||||
update();
|
||||
} else if (message.notification!.title! == 'message From Driver') {
|
||||
passengerDialog(message.notification!.body!);
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController()
|
||||
.showNotification('message From passenger'.tr, ''.tr, 'tone2');
|
||||
notificationController.showNotification(
|
||||
'message From passenger'.tr, ''.tr, 'tone2');
|
||||
}
|
||||
passengerDialog(message.notification!.body!);
|
||||
|
||||
update();
|
||||
} else if (message.notification!.title! == 'RideIsBegin'.tr) {
|
||||
if (Platform.isAndroid) {
|
||||
notificationController.showNotification(
|
||||
'Trip is Begin'.tr, ''.tr, 'start');
|
||||
}
|
||||
Get.find<MapPassengerController>().getBeginRideFromDriver();
|
||||
// Get.snackbar('RideIsBegin', '', backgroundColor: AppColor.greenColor);
|
||||
box.write(BoxName.passengerWalletTotal, '0');
|
||||
update();
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController()
|
||||
.showNotification('Trip is Begin'.tr, ''.tr, 'start');
|
||||
}
|
||||
} else if (message.notification!.title! == 'Hi ,I will go now'.tr) {
|
||||
// Get.snackbar('Hi ,I will go now', '',
|
||||
// backgroundColor: AppColor.greenColor);
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController().showNotification(
|
||||
notificationController.showNotification(
|
||||
'Passenger come to you'.tr, 'Hi ,I will go now'.tr, 'tone2');
|
||||
}
|
||||
update();
|
||||
} else if (message.notification!.title! == 'Hi ,I Arrive your site'.tr) {
|
||||
driverArrivePassengerDialoge();
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController()
|
||||
.showNotification('Hi ,I Arrive your site'.tr, ''.tr, 'tone2');
|
||||
notificationController.showNotification(
|
||||
'Hi ,I Arrive your site'.tr, ''.tr, 'tone2');
|
||||
}
|
||||
update();
|
||||
} else if (message.notification!.title! == "Cancel Trip from driver".tr) {
|
||||
Get.back();
|
||||
|
||||
Get.defaultDialog(
|
||||
title: "The driver canceled your ride.".tr,
|
||||
middleText: "We will look for a new driver.\\nPlease wait.".tr,
|
||||
middleText: "We will look for a new driver.\nPlease wait.".tr,
|
||||
confirm: MyElevatedButton(
|
||||
kolor: AppColor.greenColor,
|
||||
title: 'Ok'.tr,
|
||||
onPressed: () async {
|
||||
Get.back();
|
||||
@@ -219,6 +231,7 @@ class FirebaseMessagesController extends GetxController {
|
||||
),
|
||||
cancel: MyElevatedButton(
|
||||
title: 'Cancel'.tr,
|
||||
kolor: AppColor.redColor,
|
||||
onPressed: () {
|
||||
Get.offAll(const MapPagePassenger());
|
||||
},
|
||||
@@ -230,7 +243,7 @@ class FirebaseMessagesController extends GetxController {
|
||||
var myListString = message.data['passengerList'];
|
||||
var driverList = jsonDecode(myListString) as List<dynamic>;
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController().showNotification(
|
||||
notificationController.showNotification(
|
||||
'Driver Finish Trip'.tr,
|
||||
'you will pay to Driver'.tr + ' ${driverList[3].toString()} \$'.tr,
|
||||
'tone1');
|
||||
@@ -267,7 +280,7 @@ class FirebaseMessagesController extends GetxController {
|
||||
var driverList = jsonDecode(myListString) as List<dynamic>;
|
||||
// if (Platform.isAndroid) {
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController().showNotification(
|
||||
notificationController.showNotification(
|
||||
'Call Income'.tr,
|
||||
message.notification!.body!,
|
||||
'iphone_ringtone',
|
||||
@@ -287,7 +300,7 @@ class FirebaseMessagesController extends GetxController {
|
||||
var driverList = jsonDecode(myListString) as List<dynamic>;
|
||||
// if (Platform.isAndroid) {
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController().showNotification(
|
||||
notificationController.showNotification(
|
||||
'Call Income'.tr,
|
||||
message.notification!.body!,
|
||||
'iphone_ringtone',
|
||||
@@ -305,7 +318,7 @@ class FirebaseMessagesController extends GetxController {
|
||||
var myListString = message.data['passengerList'];
|
||||
var driverList = jsonDecode(myListString) as List<dynamic>;
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController().showNotification(
|
||||
notificationController.showNotification(
|
||||
'Call End'.tr,
|
||||
message.notification!.body!,
|
||||
'tone2',
|
||||
@@ -321,7 +334,7 @@ class FirebaseMessagesController extends GetxController {
|
||||
// 'message',
|
||||
// backgroundColor: AppColor.redColor);
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController().showNotification(
|
||||
notificationController.showNotification(
|
||||
'Driver Cancel Your Trip'.tr,
|
||||
'you will pay to Driver you will be pay the cost of driver time look to your SEFER Wallet'
|
||||
.tr,
|
||||
@@ -346,7 +359,7 @@ class FirebaseMessagesController extends GetxController {
|
||||
|
||||
else if (message.notification!.title! == 'Order Applied'.tr) {
|
||||
if (Platform.isAndroid) {
|
||||
NotificationController().showNotification(
|
||||
notificationController.showNotification(
|
||||
'The order Accepted by another Driver'.tr,
|
||||
'We regret to inform you that another driver has accepted this order.'
|
||||
.tr,
|
||||
@@ -604,120 +617,6 @@ class FirebaseMessagesController extends GetxController {
|
||||
}
|
||||
}
|
||||
|
||||
void sendNotificationToAnyWithoutData(
|
||||
String title, String body, String token, 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();
|
||||
// Log.print('accessToken: ${accessToken}');
|
||||
|
||||
// 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,
|
||||
},
|
||||
'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 token: ${token}');
|
||||
} else {
|
||||
print(
|
||||
'Failed to send notification. Status code: ${response.statusCode}');
|
||||
print('Response body: ${response.body}');
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error sending notification: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// void sendNotificationToDriverMAP(String title, String body, String token,
|
||||
// List<String> data, String tone) async {
|
||||
// try {
|
||||
// final response = await http.post(
|
||||
// // Uri.parse(
|
||||
// // 'https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send'),
|
||||
// Uri.parse('https://fcm.googleapis.com/fcm/send'),
|
||||
// headers: <String, String>{
|
||||
// 'Content-Type': 'application/json',
|
||||
// // 'Authorization': 'Bearer 104815009508844392546'
|
||||
// 'Authorization': 'key=${AK.serverAPI}'
|
||||
// },
|
||||
// body: jsonEncode({
|
||||
// 'notification': <String, dynamic>{
|
||||
// 'title': title,
|
||||
// 'body': body,
|
||||
// 'sound': tone
|
||||
// },
|
||||
// 'data': {
|
||||
// 'DriverList': data,
|
||||
// },
|
||||
// 'priority': 'high',
|
||||
// 'to': token,
|
||||
// }),
|
||||
// );
|
||||
|
||||
// if (response.statusCode == 200) {
|
||||
// Log.print(
|
||||
// 'Notification sent successfully. Status code: ${response.statusCode}');
|
||||
// Log.print('Response body: ${response.body}');
|
||||
// } else {
|
||||
// Log.print(
|
||||
// 'Failed to send notification. Status code: ${response.statusCode}');
|
||||
// Log.print('Response body: ${response.body}');
|
||||
// }
|
||||
// } catch (e) {
|
||||
// Log.print('Error sending notification: $e');
|
||||
// }
|
||||
// }
|
||||
|
||||
Future<void> sendNotificationToDriverMAP(
|
||||
String title, String body, String token, List<String> data, String tone,
|
||||
{int retryCount = 2}) async {
|
||||
@@ -809,79 +708,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 DriverTipWidget extends StatelessWidget {
|
||||
|
||||
@@ -1,29 +1,219 @@
|
||||
// import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
// import 'package:get/get.dart';
|
||||
// import 'package:timezone/data/latest.dart' as tz;
|
||||
// import 'package:timezone/timezone.dart' as tz;
|
||||
|
||||
// class NotificationController extends GetxController {
|
||||
// final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
|
||||
// FlutterLocalNotificationsPlugin();
|
||||
|
||||
// // Initializes the local notifications plugin
|
||||
// Future<void> initNotifications() async {
|
||||
// const AndroidInitializationSettings android =
|
||||
// AndroidInitializationSettings('@mipmap/launcher_icon');
|
||||
// const InitializationSettings initializationSettings =
|
||||
// InitializationSettings(android: android);
|
||||
// await _flutterLocalNotificationsPlugin.initialize(initializationSettings);
|
||||
// }
|
||||
|
||||
// // Displays a notification with the given title and message
|
||||
// void showNotification(String title, String message, String tone) async {
|
||||
// AndroidNotificationDetails android = AndroidNotificationDetails(
|
||||
// 'high_importance_channel',
|
||||
// 'High Importance Notifications',
|
||||
// importance: Importance.max,
|
||||
// priority: Priority.high,
|
||||
// showWhen: false,
|
||||
// sound: RawResourceAndroidNotificationSound(tone),
|
||||
// );
|
||||
// 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);
|
||||
// }
|
||||
|
||||
// // Schedules a notification after 1 minute
|
||||
// void scheduleNotificationAfter1Minute(
|
||||
// String title, String message, String tone) async {
|
||||
// AndroidNotificationDetails android = AndroidNotificationDetails(
|
||||
// 'high_importance_channel', 'High Importance Notifications',
|
||||
// importance: Importance.max,
|
||||
// priority: Priority.high,
|
||||
// showWhen: false,
|
||||
// sound: RawResourceAndroidNotificationSound(tone));
|
||||
|
||||
// DarwinNotificationDetails ios = const DarwinNotificationDetails(
|
||||
// sound: 'default',
|
||||
// presentAlert: true,
|
||||
// presentBadge: true,
|
||||
// presentSound: true,
|
||||
// );
|
||||
|
||||
// NotificationDetails details =
|
||||
// NotificationDetails(android: android, iOS: ios);
|
||||
|
||||
// // Schedule the notification to be shown after 1 minute
|
||||
// final now = tz.TZDateTime.now(tz.local);
|
||||
// final scheduledTime = now.add(const Duration(minutes: 1));
|
||||
|
||||
// await _flutterLocalNotificationsPlugin.zonedSchedule(
|
||||
// 0,
|
||||
// title,
|
||||
// message,
|
||||
// scheduledTime,
|
||||
// details,
|
||||
// androidAllowWhileIdle: true,
|
||||
// uiLocalNotificationDateInterpretation:
|
||||
// UILocalNotificationDateInterpretation.absoluteTime,
|
||||
// matchDateTimeComponents: DateTimeComponents.time,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:SEFER/constant/box_name.dart';
|
||||
import 'package:SEFER/main.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;
|
||||
|
||||
class NotificationController extends GetxController {
|
||||
final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
|
||||
FlutterLocalNotificationsPlugin();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
initNotifications();
|
||||
}
|
||||
|
||||
// Initializes the local notifications plugin
|
||||
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);
|
||||
await _flutterLocalNotificationsPlugin.initialize(initializationSettings);
|
||||
|
||||
tz.initializeTimeZones();
|
||||
print('Notifications initialized');
|
||||
}
|
||||
|
||||
// Displays a notification with the given title and message
|
||||
void showNotification(String title, String message, String tone) async {
|
||||
AndroidNotificationDetails android = AndroidNotificationDetails(
|
||||
'high_importance_channel', 'High Importance Notifications',
|
||||
importance: Importance.max,
|
||||
priority: Priority.high,
|
||||
showWhen: false,
|
||||
sound: RawResourceAndroidNotificationSound(tone));
|
||||
final AndroidNotificationDetails android = AndroidNotificationDetails(
|
||||
'high_importance_channel',
|
||||
'High Importance Notifications',
|
||||
importance: Importance.max,
|
||||
priority: Priority.high,
|
||||
showWhen: false,
|
||||
sound: RawResourceAndroidNotificationSound(tone),
|
||||
);
|
||||
|
||||
NotificationDetails details = NotificationDetails(android: android);
|
||||
const DarwinNotificationDetails ios = DarwinNotificationDetails(
|
||||
sound: 'default',
|
||||
presentAlert: true,
|
||||
presentBadge: true,
|
||||
presentSound: true,
|
||||
);
|
||||
|
||||
final NotificationDetails details =
|
||||
NotificationDetails(android: android, iOS: ios);
|
||||
await _flutterLocalNotificationsPlugin.show(0, title, message, details);
|
||||
print('Notification shown: $title - $message');
|
||||
}
|
||||
|
||||
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(8, 0, title, message, details);
|
||||
await _scheduleNotificationForTime(15, 0, title, message, details);
|
||||
await _scheduleNotificationForTime(20, 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();
|
||||
var cairoLocation;
|
||||
if (box.read(BoxName.countryCode).toString() == 'Egypt') {
|
||||
cairoLocation = tz.getLocation('Africa/Cairo');
|
||||
} else {} // todo get for location country
|
||||
// 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');
|
||||
}
|
||||
}
|
||||
|
||||
19
lib/controller/functions/add_error.dart
Normal file
19
lib/controller/functions/add_error.dart
Normal file
@@ -0,0 +1,19 @@
|
||||
import '../../constant/box_name.dart';
|
||||
import '../../constant/links.dart';
|
||||
import '../../main.dart';
|
||||
import 'crud.dart';
|
||||
|
||||
addError(String error, where) async {
|
||||
CRUD().post(link: AppLink.addError, payload: {
|
||||
'error': error.toString(), // Example error description
|
||||
'userId': box.read(BoxName.driverID) ??
|
||||
box.read(BoxName.passengerID), // Example user ID
|
||||
'userType': box.read(BoxName.driverID) != null
|
||||
? 'Driver'
|
||||
: 'passenger', // Example user type
|
||||
'phone': box.read(BoxName.phone) ??
|
||||
box.read(BoxName.phoneDriver), // Example phone number
|
||||
|
||||
'device': where
|
||||
});
|
||||
}
|
||||
@@ -1,15 +1,21 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:ui';
|
||||
import 'package:SEFER/constant/box_name.dart';
|
||||
import 'package:SEFER/constant/links.dart';
|
||||
import 'package:SEFER/main.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:SEFER/env/env.dart';
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
import 'package:mime/mime.dart';
|
||||
|
||||
import '../../constant/api_key.dart';
|
||||
|
||||
import '../../constant/colors.dart';
|
||||
import '../../print.dart';
|
||||
import '../../views/widgets/elevated_btn.dart';
|
||||
import 'add_error.dart';
|
||||
import 'upload_image.dart';
|
||||
|
||||
class CRUD {
|
||||
@@ -29,8 +35,9 @@ class CRUD {
|
||||
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}',
|
||||
},
|
||||
);
|
||||
Log.print('payload: ${payload}');
|
||||
|
||||
Log.print('response.request: ${response.request}');
|
||||
Log.print('payload: ${payload}');
|
||||
Log.print('response.reasonPhrase: ${response.reasonPhrase}');
|
||||
|
||||
Log.print('response.body: ${response.body}');
|
||||
@@ -44,7 +51,6 @@ class CRUD {
|
||||
return jsonData['status'];
|
||||
}
|
||||
|
||||
// }
|
||||
Future<dynamic> getTokenParent({
|
||||
required String link,
|
||||
Map<String, dynamic>? payload,
|
||||
@@ -264,36 +270,83 @@ class CRUD {
|
||||
} else {}
|
||||
}
|
||||
|
||||
// Future<dynamic> post({
|
||||
// required String link,
|
||||
// Map<String, dynamic>? payload,
|
||||
// }) async {
|
||||
// // String? basicAuthCredentials =
|
||||
// // await storage.read(key: BoxName.basicAuthCredentials);
|
||||
// var url = Uri.parse(
|
||||
// link,
|
||||
// );
|
||||
// var response = await http.post(
|
||||
// url,
|
||||
// body: payload,
|
||||
// headers: {
|
||||
// "Content-Type": "application/x-www-form-urlencoded",
|
||||
// 'Authorization':
|
||||
// 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
|
||||
// },
|
||||
// );
|
||||
// Log.print('payload: ${payload}');
|
||||
// Log.print('response.request: ${response.request}');
|
||||
// Log.print('response.body: ${response.body}');
|
||||
// var jsonData = jsonDecode(response.body);
|
||||
// if (response.statusCode == 200) {
|
||||
// if (jsonData['status'] == 'success') {
|
||||
// return response.body;
|
||||
// } else {
|
||||
// return (jsonData['status']);
|
||||
// }
|
||||
// } else {
|
||||
// return response.statusCode;
|
||||
// }
|
||||
// }
|
||||
Future<dynamic> post({
|
||||
required String link,
|
||||
Map<String, dynamic>? payload,
|
||||
}) async {
|
||||
// String? basicAuthCredentials =
|
||||
// await storage.read(key: BoxName.basicAuthCredentials);
|
||||
var url = Uri.parse(
|
||||
link,
|
||||
);
|
||||
var response = await http.post(
|
||||
url,
|
||||
body: payload,
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
'Authorization':
|
||||
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
|
||||
},
|
||||
);
|
||||
Log.print('payload: ${payload}');
|
||||
Log.print('response.request: ${response.request}');
|
||||
Log.print('response.body: ${response.body}');
|
||||
var jsonData = jsonDecode(response.body);
|
||||
if (response.statusCode == 200) {
|
||||
if (jsonData['status'] == 'success') {
|
||||
return response.body;
|
||||
var url = Uri.parse(link);
|
||||
try {
|
||||
var response = await http.post(
|
||||
url,
|
||||
body: payload,
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
'Authorization':
|
||||
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
|
||||
},
|
||||
);
|
||||
|
||||
Log.print('Response.request: ${response.request}');
|
||||
Log.print('Payload: $payload');
|
||||
// Log.print('Response.statusCode: ${response.statusCode}');
|
||||
Log.print('Response.body: ${response.body}');
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
try {
|
||||
var jsonData = jsonDecode(response.body);
|
||||
|
||||
if (jsonData['status'] == 'success') {
|
||||
return jsonData;
|
||||
} else {
|
||||
return jsonData['status'];
|
||||
}
|
||||
} catch (e) {
|
||||
Log.print('JSON parsing error: $e');
|
||||
addError(e.toString(), 'crud().post');
|
||||
return 'failure'; // Return a recognizable failure string for JSON errors
|
||||
}
|
||||
} else {
|
||||
return (jsonData['status']);
|
||||
Log.print('Non-200 response code: ${response.statusCode}');
|
||||
addError(
|
||||
'Non-200 response code: ${response.statusCode}', 'crud().post');
|
||||
return 'failure'; // Handle unexpected status codes as failures
|
||||
}
|
||||
} else {
|
||||
return response.statusCode;
|
||||
} catch (e) {
|
||||
Log.print('HTTP request error: $e');
|
||||
addError('HTTP request error: $e', 'crud().post');
|
||||
return 'failure'; // Handle HTTP request errors as failures
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class SmsEgyptController extends GetxController {
|
||||
Future<dynamic> sendSmsEgypt(String phone, otp) async {
|
||||
String sender = await getSender();
|
||||
var body = jsonEncode({
|
||||
"username": AppInformation.appName,
|
||||
"username": 'Sefer',
|
||||
"password": AK.smsPasswordEgypt,
|
||||
"message": "${AppInformation.appName} app code is $otp\ncopy it to app",
|
||||
"language": box.read(BoxName.lang) == 'en' ? "e" : 'r',
|
||||
|
||||
@@ -1,49 +1,50 @@
|
||||
import 'package:SEFER/constant/box_name.dart';
|
||||
import 'package:SEFER/main.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_tts/flutter_tts.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../main.dart';
|
||||
|
||||
class TextToSpeechController extends GetxController {
|
||||
final flutterTts = FlutterTts();
|
||||
|
||||
// Initialize TTS in initState
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
initTts();
|
||||
}
|
||||
|
||||
// Dispose of TTS when controller is closed
|
||||
@override
|
||||
void onClose() {
|
||||
flutterTts.stop(); // Stop any ongoing TTS
|
||||
super.onClose();
|
||||
flutterTts.completionHandler;
|
||||
}
|
||||
|
||||
// Function to initialize TTS engine
|
||||
// Initialize TTS engine with language check
|
||||
Future<void> initTts() async {
|
||||
String? lang =
|
||||
WidgetsBinding.instance.platformDispatcher.locale.countryCode;
|
||||
await flutterTts
|
||||
.setLanguage(box.read(BoxName.lang).toString()); //'en-US' Set language
|
||||
// await flutterTts.setLanguage('ar-SA'); //'en-US' Set language
|
||||
// await flutterTts.setLanguage(lang!); //'en-US' Set language
|
||||
await flutterTts.setSpeechRate(0.5); // Adjust speech rate
|
||||
await flutterTts.setVolume(1.0); // Set volume
|
||||
try {
|
||||
String langCode = box.read(BoxName.lang) ?? 'en-US';
|
||||
bool isAvailable = await flutterTts.isLanguageAvailable(langCode);
|
||||
|
||||
// If language is unavailable, default to 'en-US'
|
||||
if (!isAvailable) {
|
||||
langCode = 'en-US';
|
||||
}
|
||||
|
||||
await flutterTts.setLanguage(langCode);
|
||||
await flutterTts.setSpeechRate(0.5); // Adjust speech rate
|
||||
await flutterTts.setVolume(1.0); // Set volume
|
||||
} catch (error) {
|
||||
Get.snackbar('Error', 'Failed to initialize TTS: $error');
|
||||
}
|
||||
}
|
||||
|
||||
// Function to speak the given text
|
||||
Future<void> speakText(String text) async {
|
||||
try {
|
||||
await flutterTts.awaitSpeakCompletion(true);
|
||||
var result = await flutterTts.speak(text);
|
||||
if (result == 1) {
|
||||
// TTS operation has started
|
||||
// You can perform additional operations here, if needed
|
||||
}
|
||||
await flutterTts.speak(text);
|
||||
} catch (error) {
|
||||
// Handle error gracefully, e.g., show a message
|
||||
Get.snackbar('Error', 'Failed to speak text: $error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -769,7 +769,8 @@ class MapPassengerController extends GetxController {
|
||||
if (res != 'failure') {
|
||||
var decode = jsonDecode(res);
|
||||
|
||||
if (decode['data']['status'] != 'Apply') {
|
||||
// if (decode['data']['status'] != 'Apply') {
|
||||
if (decode['data']['status'] == 'Begin') {
|
||||
timeToPassengerFromDriverAfterApplied = 0;
|
||||
remainingTime = 0;
|
||||
remainingTimeToPassengerFromDriverAfterApplied = 0;
|
||||
@@ -1077,7 +1078,7 @@ class MapPassengerController extends GetxController {
|
||||
// licensePlate = nearestDriverData['car_plate'].toString();
|
||||
// startCarLocationSearch(box.read(BoxName.carType));
|
||||
await getCarsLocationByPassengerAndReloadMarker(
|
||||
box.read(BoxName.carType), 4500);
|
||||
box.read(BoxName.carType), 3000);
|
||||
// await getCarsLocationByPassengerAndReloadMarker(
|
||||
// box.read(BoxName.carType), 7000);
|
||||
// await getNearestDriverByPassengerLocation();
|
||||
@@ -1112,26 +1113,28 @@ class MapPassengerController extends GetxController {
|
||||
isDriversTokensSend = false;
|
||||
|
||||
update();
|
||||
await CRUD()
|
||||
.post(link: "${AppLink.endPoint}/ride/rides/add.php", payload: {
|
||||
"start_location": //'${data[0]['start_address']}',
|
||||
'${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
|
||||
"end_location": //'${data[0]['end_address']}',
|
||||
'${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
|
||||
"date": DateTime.now().toString(),
|
||||
"time": DateTime.now().toString(),
|
||||
"endtime": durationToAdd.toString(),
|
||||
"price": totalPassenger.toStringAsFixed(2),
|
||||
"passenger_id": box.read(BoxName.passengerID).toString(),
|
||||
"driver_id": dataCarsLocationByPassenger['data'][carsOrder]['driver_id']
|
||||
.toString(),
|
||||
"status": "waiting",
|
||||
'carType': box.read(BoxName.carType),
|
||||
"price_for_driver": totalPassenger.toString(),
|
||||
"price_for_passenger": totalME.toString(),
|
||||
"distance": distance.toString(),
|
||||
"paymentMethod": paymentController.isWalletChecked.toString(),
|
||||
}).then((value) {
|
||||
await CRUD().post(
|
||||
link: "${AppLink.seferCairoServer}/ride/rides/add.php",
|
||||
payload: {
|
||||
"start_location": //'${data[0]['start_address']}',
|
||||
'${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
|
||||
"end_location": //'${data[0]['end_address']}',
|
||||
'${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
|
||||
"date": DateTime.now().toString(),
|
||||
"time": DateTime.now().toString(),
|
||||
"endtime": durationToAdd.toString(),
|
||||
"price": totalPassenger.toStringAsFixed(2),
|
||||
"passenger_id": box.read(BoxName.passengerID).toString(),
|
||||
"driver_id": dataCarsLocationByPassenger['data'][carsOrder]
|
||||
['driver_id']
|
||||
.toString(),
|
||||
"status": "waiting",
|
||||
'carType': box.read(BoxName.carType),
|
||||
"price_for_driver": totalPassenger.toString(),
|
||||
"price_for_passenger": totalME.toString(),
|
||||
"distance": distance.toString(),
|
||||
"paymentMethod": paymentController.isWalletChecked.toString(),
|
||||
}).then((value) {
|
||||
// List<String> body = [
|
||||
rideId = jsonDecode(value)['message'];
|
||||
List<String> body = [
|
||||
@@ -1188,6 +1191,29 @@ class MapPassengerController extends GetxController {
|
||||
Log.print(
|
||||
'dataCarsLocationByPassenger[data]: ${dataCarsLocationByPassenger['data'][carsOrder]['token']}');
|
||||
});
|
||||
|
||||
if (AppLink.endPoint != AppLink.seferCairoServer) {
|
||||
CRUD().post(link: "${AppLink.endPoint}/ride/rides/add.php", payload: {
|
||||
"start_location": //'${data[0]['start_address']}',
|
||||
'${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
|
||||
"end_location": //'${data[0]['end_address']}',
|
||||
'${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
|
||||
"date": DateTime.now().toString(),
|
||||
"time": DateTime.now().toString(),
|
||||
"endtime": durationToAdd.toString(),
|
||||
"price": totalPassenger.toStringAsFixed(2),
|
||||
"passenger_id": box.read(BoxName.passengerID).toString(),
|
||||
"driver_id": dataCarsLocationByPassenger['data'][carsOrder]
|
||||
['driver_id']
|
||||
.toString(),
|
||||
"status": "waiting",
|
||||
'carType': box.read(BoxName.carType),
|
||||
"price_for_driver": totalPassenger.toString(),
|
||||
"price_for_passenger": totalME.toString(),
|
||||
"distance": distance.toString(),
|
||||
"paymentMethod": paymentController.isWalletChecked.toString(),
|
||||
});
|
||||
}
|
||||
delayAndFetchRideStatus(rideId, box.read(BoxName.carType));
|
||||
if (shouldFetch == false) {
|
||||
startTimer();
|
||||
@@ -1211,10 +1237,11 @@ class MapPassengerController extends GetxController {
|
||||
}
|
||||
}
|
||||
|
||||
String driverOrderStatus = 'yet';
|
||||
bool isDriversTokensSend = false;
|
||||
confirmRideForAllDriverAvailable() async {
|
||||
confirmRideForAllDriverAvailable0() async {
|
||||
await getCarsLocationByPassengerAndReloadMarker(
|
||||
box.read(BoxName.carType), 4500);
|
||||
box.read(BoxName.carType), 3500);
|
||||
if (dataCarsLocationByPassenger != 'failure') {
|
||||
// driversToken.remove(driverToken);
|
||||
PaymentController paymentController = Get.find<PaymentController>();
|
||||
@@ -1291,33 +1318,38 @@ class MapPassengerController extends GetxController {
|
||||
// Log.print('body: ${body}');
|
||||
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
'OrderSpeed',
|
||||
rideId.toString(),
|
||||
dataCarsLocationByPassenger['data'][i]['token'].toString(),
|
||||
body,
|
||||
'order.wav');
|
||||
'OrderSpeed',
|
||||
rideId.toString(),
|
||||
dataCarsLocationByPassenger['data'][i]['token'].toString(),
|
||||
body,
|
||||
'order.wav',
|
||||
);
|
||||
driverOrderStatus = 'recive';
|
||||
}
|
||||
});
|
||||
(rideId); //
|
||||
CRUD().post(link: '${AppLink.endPoint}/ride/rides/add.php', payload: {
|
||||
"start_location": //'${data[0]['start_address']}',
|
||||
'${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
|
||||
"end_location": //'${data[0]['end_address']}',
|
||||
'${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
|
||||
"date": DateTime.now().toString(),
|
||||
"time": DateTime.now().toString(),
|
||||
"endtime": durationToAdd.toString(),
|
||||
"price": totalPassenger.toStringAsFixed(2),
|
||||
"passenger_id": box.read(BoxName.passengerID).toString(),
|
||||
"driver_id": dataCarsLocationByPassenger['data'][carsOrder]['driver_id']
|
||||
.toString(),
|
||||
"status": "waiting",
|
||||
'carType': box.read(BoxName.carType),
|
||||
"price_for_driver": totalPassenger.toString(),
|
||||
"price_for_passenger": totalME.toString(),
|
||||
"distance": distance.toString(),
|
||||
"paymentMethod": paymentController.isWalletChecked.toString(),
|
||||
});
|
||||
if (AppLink.endPoint != AppLink.seferCairoServer) {
|
||||
CRUD().post(link: '${AppLink.endPoint}/ride/rides/add.php', payload: {
|
||||
"start_location": //'${data[0]['start_address']}',
|
||||
'${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
|
||||
"end_location": //'${data[0]['end_address']}',
|
||||
'${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
|
||||
"date": DateTime.now().toString(),
|
||||
"time": DateTime.now().toString(),
|
||||
"endtime": durationToAdd.toString(),
|
||||
"price": totalPassenger.toStringAsFixed(2),
|
||||
"passenger_id": box.read(BoxName.passengerID).toString(),
|
||||
"driver_id": dataCarsLocationByPassenger['data'][carsOrder]
|
||||
['driver_id']
|
||||
.toString(),
|
||||
"status": "waiting",
|
||||
'carType': box.read(BoxName.carType),
|
||||
"price_for_driver": totalPassenger.toString(),
|
||||
"price_for_passenger": totalME.toString(),
|
||||
"distance": distance.toString(),
|
||||
"paymentMethod": paymentController.isWalletChecked.toString(),
|
||||
});
|
||||
}
|
||||
|
||||
delayAndFetchRideStatusForAllDriverAvailable(rideId);
|
||||
update();
|
||||
@@ -1330,6 +1362,344 @@ class MapPassengerController extends GetxController {
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> notifiedDrivers = {};
|
||||
|
||||
confirmRideForAllDriverAvailable() async {
|
||||
// Fetch car locations
|
||||
await getCarsLocationByPassengerAndReloadMarker(
|
||||
box.read(BoxName.carType), 3000);
|
||||
|
||||
// Ensure dataCarsLocationByPassenger is not 'failure' or null
|
||||
if (dataCarsLocationByPassenger != 'failure' &&
|
||||
dataCarsLocationByPassenger != null) {
|
||||
// Check if 'data' key exists and is not null
|
||||
if (dataCarsLocationByPassenger.containsKey('data') &&
|
||||
dataCarsLocationByPassenger['data'] != null) {
|
||||
PaymentController paymentController = Get.find<PaymentController>();
|
||||
rideConfirm = true;
|
||||
shouldFetch = true;
|
||||
isBottomSheetShown = false;
|
||||
timeToPassengerFromDriverAfterApplied = 60;
|
||||
|
||||
// Add ride to database
|
||||
await CRUD().post(
|
||||
link: "${AppLink.seferCairoServer}/ride/rides/add.php",
|
||||
payload: {
|
||||
"start_location":
|
||||
'${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
|
||||
"end_location":
|
||||
'${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
|
||||
"date": DateTime.now().toString(),
|
||||
"time": DateTime.now().toString(),
|
||||
"endtime": durationToAdd.toString(),
|
||||
"price": totalPassenger.toStringAsFixed(2),
|
||||
"passenger_id": box.read(BoxName.passengerID).toString(),
|
||||
"driver_id": dataCarsLocationByPassenger['data'][carsOrder]
|
||||
['driver_id']
|
||||
.toString(),
|
||||
"status": "waiting",
|
||||
'carType': box.read(BoxName.carType),
|
||||
"price_for_driver": totalPassenger.toString(),
|
||||
"price_for_passenger": totalME.toString(),
|
||||
"distance": distance.toString(),
|
||||
"paymentMethod": paymentController.isWalletChecked.toString(),
|
||||
}).then((value) {
|
||||
if (value is String) {
|
||||
final parsedValue = jsonDecode(value);
|
||||
rideId = parsedValue['message'];
|
||||
} else if (value is Map) {
|
||||
rideId = value['message'];
|
||||
} else {
|
||||
Log.print('Unexpected response type: ${value.runtimeType}');
|
||||
}
|
||||
// Log.print('value: ${value}');
|
||||
// rideId = jsonDecode(value)['message'];
|
||||
// rideId = jsonDecode(value)['message'].toString();
|
||||
|
||||
// Timer for 5 iterations, runs every 2 seconds
|
||||
int iteration = 0;
|
||||
Timer.periodic(const Duration(seconds: 2), (timer) async {
|
||||
if (iteration >= 5) {
|
||||
timer.cancel();
|
||||
return;
|
||||
}
|
||||
iteration++;
|
||||
|
||||
// Reload driver locations
|
||||
await getCarsLocationByPassengerAndReloadMarker(
|
||||
box.read(BoxName.carType), 3000);
|
||||
|
||||
// Ensure dataCarsLocationByPassenger and data key are still valid
|
||||
if (dataCarsLocationByPassenger != null &&
|
||||
dataCarsLocationByPassenger.containsKey('data') &&
|
||||
dataCarsLocationByPassenger['data'] != null) {
|
||||
// Notify only new drivers
|
||||
for (var driverData in dataCarsLocationByPassenger['data']) {
|
||||
String driverId = driverData['driver_id'].toString();
|
||||
if (!notifiedDrivers.contains(driverId)) {
|
||||
notifiedDrivers.add(driverId);
|
||||
|
||||
// Prepare body payload for notification
|
||||
List<String> body = [
|
||||
'${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
|
||||
'${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
|
||||
totalPassenger.toStringAsFixed(2),
|
||||
totalDriver.toStringAsFixed(2),
|
||||
durationToRide.toString(),
|
||||
distance.toStringAsFixed(2),
|
||||
driverId,
|
||||
box.read(BoxName.passengerID).toString(),
|
||||
box.read(BoxName.name).toString(),
|
||||
box.read(BoxName.tokenFCM).toString(),
|
||||
box.read(BoxName.phone).toString(),
|
||||
durationByPassenger.toString(),
|
||||
distanceByPassenger.toString(),
|
||||
paymentController.isWalletChecked.toString(),
|
||||
driverData['token'].toString(),
|
||||
durationToPassenger.toString(),
|
||||
rideId,
|
||||
rideTimerBegin.toString(),
|
||||
driverId,
|
||||
durationToRide.toString(),
|
||||
Get.find<WayPointController>().wayPoints.length > 1
|
||||
? 'haveSteps'
|
||||
: 'startEnd',
|
||||
placesCoordinate[0],
|
||||
placesCoordinate[1],
|
||||
placesCoordinate[2],
|
||||
placesCoordinate[3],
|
||||
placesCoordinate[4],
|
||||
costForDriver.toStringAsFixed(2),
|
||||
(double.parse(box.read(BoxName.passengerWalletTotal)) < 0
|
||||
? double.parse(box.read(BoxName.passengerWalletTotal))
|
||||
.toStringAsFixed(2)
|
||||
: '0'),
|
||||
box.read(BoxName.email).toString(),
|
||||
data[0]['start_address'],
|
||||
data[0]['end_address'],
|
||||
box.read(BoxName.carType),
|
||||
kazan.toStringAsFixed(0),
|
||||
passengerRate.toStringAsFixed(2),
|
||||
];
|
||||
|
||||
// Send notification to the driver
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
'OrderSpeed',
|
||||
rideId,
|
||||
driverData['token'].toString(),
|
||||
body,
|
||||
'order.wav',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Check for additional server endpoint
|
||||
if (AppLink.endPoint != AppLink.seferCairoServer) {
|
||||
CRUD().post(link: '${AppLink.endPoint}/ride/rides/add.php', payload: {
|
||||
"start_location":
|
||||
'${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
|
||||
"end_location":
|
||||
'${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
|
||||
"date": DateTime.now().toString(),
|
||||
"time": DateTime.now().toString(),
|
||||
"endtime": durationToAdd.toString(),
|
||||
"price": totalPassenger.toStringAsFixed(2),
|
||||
"passenger_id": box.read(BoxName.passengerID).toString(),
|
||||
"driver_id": dataCarsLocationByPassenger['data'][carsOrder]
|
||||
['driver_id']
|
||||
.toString(),
|
||||
"status": "waiting",
|
||||
'carType': box.read(BoxName.carType),
|
||||
"price_for_driver": totalPassenger.toString(),
|
||||
"price_for_passenger": totalME.toString(),
|
||||
"distance": distance.toString(),
|
||||
"paymentMethod": paymentController.isWalletChecked.toString(),
|
||||
});
|
||||
}
|
||||
delayAndFetchRideStatusForAllDriverAvailable(rideId);
|
||||
update();
|
||||
} else {
|
||||
// Show dialog if no drivers found in data key
|
||||
MyDialog().getDialog("No Car or Driver Found in your area.".tr,
|
||||
"No Car or Driver Found in your area.".tr, () {
|
||||
Get.back();
|
||||
Get.offAll(const MapPagePassenger());
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Show dialog if dataCarsLocationByPassenger is 'failure' or null
|
||||
MyDialog().getDialog("No Car or Driver Found in your area.".tr,
|
||||
"No Car or Driver Found in your area.".tr, () {
|
||||
Get.back();
|
||||
Get.offAll(const MapPagePassenger());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
confirmRideForAllDriverAvailable1() async {
|
||||
int attempts = 0;
|
||||
const int maxAttempts = 4;
|
||||
const Duration delayDuration = Duration(seconds: 2);
|
||||
|
||||
// Initial data fetch
|
||||
await getCarsLocationByPassengerAndReloadMarker(
|
||||
box.read(BoxName.carType), 3000);
|
||||
|
||||
if (dataCarsLocationByPassenger != null &&
|
||||
dataCarsLocationByPassenger != 'failure') {
|
||||
PaymentController paymentController = Get.find<PaymentController>();
|
||||
rideConfirm = true;
|
||||
shouldFetch = true;
|
||||
isBottomSheetShown = false;
|
||||
timeToPassengerFromDriverAfterApplied = 60;
|
||||
|
||||
// Create a set to keep track of notified driver IDs
|
||||
Set<String> notifiedDriverIds = {};
|
||||
|
||||
// Send the initial ride request once
|
||||
rideId = await CRUD().post(
|
||||
link: "${AppLink.seferCairoServer}/ride/rides/add.php",
|
||||
payload: {
|
||||
"start_location":
|
||||
'${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
|
||||
"end_location":
|
||||
'${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
|
||||
"date": DateTime.now().toString(),
|
||||
"time": DateTime.now().toString(),
|
||||
"endtime": durationToAdd.toString(),
|
||||
"price": totalPassenger.toStringAsFixed(2),
|
||||
"passenger_id": box.read(BoxName.passengerID).toString(),
|
||||
"driver_id": dataCarsLocationByPassenger['data'][carsOrder]
|
||||
['driver_id']
|
||||
.toString(),
|
||||
"status": "waiting",
|
||||
'carType': box.read(BoxName.carType),
|
||||
"price_for_driver": totalPassenger.toString(),
|
||||
"price_for_passenger": totalME.toString(),
|
||||
"distance": distance.toString(),
|
||||
"paymentMethod": paymentController.isWalletChecked.toString(),
|
||||
}).then((value) => jsonDecode(value)['message']);
|
||||
|
||||
if (AppLink.endPoint != AppLink.seferCairoServer) {
|
||||
CRUD().post(link: '${AppLink.endPoint}/ride/rides/add.php', payload: {
|
||||
"start_location": //'${data[0]['start_address']}',
|
||||
'${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
|
||||
"end_location": //'${data[0]['end_address']}',
|
||||
'${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
|
||||
"date": DateTime.now().toString(),
|
||||
"time": DateTime.now().toString(),
|
||||
"endtime": durationToAdd.toString(),
|
||||
"price": totalPassenger.toStringAsFixed(2),
|
||||
"passenger_id": box.read(BoxName.passengerID).toString(),
|
||||
"driver_id": dataCarsLocationByPassenger['data'][carsOrder]
|
||||
['driver_id']
|
||||
.toString(),
|
||||
"status": "waiting",
|
||||
'carType': box.read(BoxName.carType),
|
||||
"price_for_driver": totalPassenger.toString(),
|
||||
"price_for_passenger": totalME.toString(),
|
||||
"distance": distance.toString(),
|
||||
"paymentMethod": paymentController.isWalletChecked.toString(),
|
||||
});
|
||||
}
|
||||
// Add the initially available drivers to the notified set
|
||||
for (var driver in dataCarsLocationByPassenger['data']) {
|
||||
notifiedDriverIds.add(driver['driver_id'].toString());
|
||||
}
|
||||
|
||||
// Periodically check for new drivers
|
||||
Timer.periodic(delayDuration, (Timer timer) async {
|
||||
attempts++;
|
||||
|
||||
await getCarsLocationByPassengerAndReloadMarker(
|
||||
box.read(BoxName.carType), 3000);
|
||||
|
||||
if (dataCarsLocationByPassenger != 'failure') {
|
||||
// Check for new drivers and notify them
|
||||
for (var driver in dataCarsLocationByPassenger['data']) {
|
||||
String driverId = driver['driver_id'].toString();
|
||||
|
||||
// Only notify new drivers
|
||||
if (!notifiedDriverIds.contains(driverId)) {
|
||||
notifiedDriverIds.add(driverId);
|
||||
|
||||
// Prepare notification body
|
||||
List<String> body = [
|
||||
'${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
|
||||
'${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
|
||||
totalPassenger.toStringAsFixed(2),
|
||||
totalDriver.toStringAsFixed(2),
|
||||
durationToRide.toString(),
|
||||
distance.toStringAsFixed(2),
|
||||
driverId,
|
||||
box.read(BoxName.passengerID).toString(),
|
||||
box.read(BoxName.name).toString(),
|
||||
box.read(BoxName.tokenFCM).toString(),
|
||||
box.read(BoxName.phone).toString(),
|
||||
durationByPassenger.toString(),
|
||||
distanceByPassenger.toString(),
|
||||
paymentController.isWalletChecked.toString(),
|
||||
driver['token'].toString(),
|
||||
durationToPassenger.toString(),
|
||||
rideId,
|
||||
rideTimerBegin.toString(),
|
||||
durationToRide.toString(),
|
||||
Get.find<WayPointController>().wayPoints.length > 1
|
||||
? 'haveSteps'
|
||||
: 'startEnd',
|
||||
placesCoordinate[0],
|
||||
placesCoordinate[1],
|
||||
placesCoordinate[2],
|
||||
placesCoordinate[3],
|
||||
placesCoordinate[4],
|
||||
costForDriver.toStringAsFixed(2),
|
||||
double.parse(box.read(BoxName.passengerWalletTotal)) < 0
|
||||
? double.parse(box.read(BoxName.passengerWalletTotal))
|
||||
.toStringAsFixed(2)
|
||||
: '0',
|
||||
box.read(BoxName.email).toString(),
|
||||
data[0]['start_address'],
|
||||
data[0]['end_address'],
|
||||
box.read(BoxName.carType),
|
||||
kazan.toStringAsFixed(0),
|
||||
passengerRate.toStringAsFixed(2),
|
||||
];
|
||||
|
||||
// Send notification to the new driver
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
'OrderSpeed',
|
||||
rideId.toString(),
|
||||
driver['token'].toString(),
|
||||
body,
|
||||
'order.wav',
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MyDialog().getDialog("No Car or Driver Found in your area.".tr,
|
||||
"No Car or Driver Found in your area.".tr, () {
|
||||
Get.back();
|
||||
Get.offAll(const MapPagePassenger());
|
||||
});
|
||||
}
|
||||
|
||||
// Stop after max attempts
|
||||
if (attempts >= maxAttempts) {
|
||||
timer.cancel();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
MyDialog().getDialog("No Car or Driver Found in your area.".tr,
|
||||
"No Car or Driver Found in your area.".tr, () {
|
||||
Get.back();
|
||||
Get.offAll(const MapPagePassenger());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
icreaseForSameRideAndDelay() {
|
||||
PaymentController paymentController = Get.find<PaymentController>();
|
||||
rideConfirm = true;
|
||||
@@ -1398,19 +1768,20 @@ class MapPassengerController extends GetxController {
|
||||
String res = await getRideStatus(rideId);
|
||||
|
||||
Log.print('tick: $tick');
|
||||
|
||||
if ((res.toString() == 'waiting' || res.toString() == 'Refused') &&
|
||||
String rideStatusDelayed = res.toString();
|
||||
if ((rideStatusDelayed == 'waiting' ||
|
||||
rideStatusDelayed == 'Refused') &&
|
||||
tick >= 15) {
|
||||
timer.cancel(); // Stop the current timer
|
||||
showAndResearchForCaptain();
|
||||
//TODO add to wait
|
||||
await getCarsLocationByPassengerAndReloadMarker(carType, 4500);
|
||||
await getCarsLocationByPassengerAndReloadMarker(carType, 3000);
|
||||
// await getNearestDriverByPassengerLocationAPIGOOGLE();
|
||||
// getCarForFirstConfirm(carType);
|
||||
confirmRideForAllDriverAvailable();
|
||||
// delayAndFetchRideStatusForAllDriverAvailable(rideId);
|
||||
} else if (res.toString() == 'Apply') {
|
||||
Log.print('res.toString() == Apply: ${res.toString()}');
|
||||
} else if (rideStatusDelayed == 'Apply') {
|
||||
Log.print('rideStatusDelayed == Apply: ${rideStatusDelayed}');
|
||||
// todo play sound
|
||||
Get.find<AudioRecorderController>()
|
||||
.playSoundFromAssets('assets/start.wav');
|
||||
@@ -1422,7 +1793,7 @@ class MapPassengerController extends GetxController {
|
||||
isSearchingWindow = false;
|
||||
update();
|
||||
startTimerFromDriverToPassengerAfterApplied();
|
||||
} else if (res.toString() == 'Refused') {
|
||||
} else if (rideStatusDelayed == 'Refused') {
|
||||
statusRide = 'Refused';
|
||||
if (isDriversTokensSend == false) {
|
||||
confirmRideForAllDriverAvailable();
|
||||
@@ -1473,17 +1844,22 @@ class MapPassengerController extends GetxController {
|
||||
attemptCounter++;
|
||||
tick++;
|
||||
var res = await getRideStatus(rideId);
|
||||
String rideStatusDelayed = res.toString();
|
||||
|
||||
if (res.toString() == 'Apply' || res.toString() == 'Applied') {
|
||||
if (rideStatusDelayed == 'Apply' || rideStatusDelayed == 'Applied') {
|
||||
await getUpdatedRideForDriverApply(rideId);
|
||||
isApplied = true;
|
||||
shouldFetch = false;
|
||||
statusRide = 'Apply';
|
||||
rideConfirm = false;
|
||||
isSearchingWindow = false;
|
||||
|
||||
startTimer();
|
||||
|
||||
update();
|
||||
startTimerFromDriverToPassengerAfterApplied();
|
||||
} else if (attemptCounter >= maxAttempts && statusRide != 'Cancel') {
|
||||
} else if (attemptCounter >= maxAttempts &&
|
||||
rideStatusDelayed != 'Cancel') {
|
||||
shouldFetch = false;
|
||||
// If the status is still not "Apply" after 15 attempts
|
||||
MyDialog().getDialog('upgrade price'.tr,
|
||||
@@ -1573,7 +1949,7 @@ class MapPassengerController extends GetxController {
|
||||
|
||||
reSearchAfterCanceledFromDriver() async {
|
||||
await getCarsLocationByPassengerAndReloadMarker(
|
||||
box.read(BoxName.carType), 4500);
|
||||
box.read(BoxName.carType), 3000);
|
||||
|
||||
confirmRideForAllDriverAvailable();
|
||||
shouldFetch = true; // Stop further fetches
|
||||
@@ -1616,8 +1992,9 @@ class MapPassengerController extends GetxController {
|
||||
}
|
||||
|
||||
Future<String> getRideStatus(String rideId) async {
|
||||
final response =
|
||||
await CRUD().get(link: AppLink.getRideStatus, payload: {'id': rideId});
|
||||
final response = await CRUD().get(
|
||||
link: "${AppLink.endPoint}/ride/rides/getRideStatus.php",
|
||||
payload: {'id': rideId});
|
||||
|
||||
return jsonDecode(response)['data'];
|
||||
}
|
||||
@@ -1638,7 +2015,7 @@ class MapPassengerController extends GetxController {
|
||||
make = response['data']['make'];
|
||||
licensePlate = response['data']['car_plate'];
|
||||
firstName = response['data']['first_name'];
|
||||
driverName = response['data']['driverName'];
|
||||
driverName = response['data']['driverName'].toString().split(' ')[0];
|
||||
driverToken = response['data']['token'];
|
||||
Log.print('driverToken updated: $driverToken');
|
||||
carYear = response['data']['year'];
|
||||
@@ -1646,10 +2023,11 @@ class MapPassengerController extends GetxController {
|
||||
}
|
||||
// driversToken.remove(driverToken);
|
||||
// for (var i = 1; i < driversToken.length; i++) {
|
||||
FirebaseMessagesController().sendNotificationToAnyWithoutData(
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
'Order Applied'.tr,
|
||||
'$driverName Apply order\nTake attention in other order'.tr,
|
||||
driverToken,
|
||||
[],
|
||||
'start.wav',
|
||||
);
|
||||
// }
|
||||
@@ -1871,6 +2249,7 @@ class MapPassengerController extends GetxController {
|
||||
longitude >= 31.215009 &&
|
||||
longitude <= 31.532186) {
|
||||
box.write(BoxName.serverChosen, AppLink.seferCairoServer);
|
||||
|
||||
return 'Cairo';
|
||||
} else if (latitude >= 29.904975 &&
|
||||
latitude <= 30.143372 &&
|
||||
@@ -2380,12 +2759,13 @@ class MapPassengerController extends GetxController {
|
||||
double tripDurationInMinutes = durationToRide / 6;
|
||||
int loopCount = tripDurationInMinutes.ceil();
|
||||
// If the trip duration is less than or equal to 50 minutes, then break the loop.
|
||||
clearMarkersExceptStartEnd();
|
||||
for (var i = 0; i < loopCount; i++) {
|
||||
// Wait for 50 seconds.
|
||||
await Future.delayed(const Duration(seconds: 4));
|
||||
if (rideTimerBegin == true && statusRide == 'Apply') {
|
||||
await getDriverCarsLocationToPassengerAfterApplied();
|
||||
}
|
||||
// if (rideTimerBegin == true && statusRide == 'Apply') {
|
||||
await getDriverCarsLocationToPassengerAfterApplied();
|
||||
// }
|
||||
reloadMarkerDriverCarsLocationToPassengerAfterApplied();
|
||||
}
|
||||
}
|
||||
@@ -2517,79 +2897,66 @@ class MapPassengerController extends GetxController {
|
||||
}
|
||||
|
||||
Future cancelRide() async {
|
||||
if (rideConfirm == false && statusRide == 'Apply' ||
|
||||
statusRide == 'Applied' ||
|
||||
statusRide == 'waiting') {
|
||||
clearPlacesDestination();
|
||||
clearPolyline();
|
||||
// clearPolylineAll();
|
||||
data = [];
|
||||
changeCancelRidePageShow();
|
||||
if (rideId != 'yet') {
|
||||
await CRUD().post(link: AppLink.updateDriverOrder, payload: {
|
||||
"order_id": rideId.toString(), // Convert to String
|
||||
"status": 'Cancel'
|
||||
});
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
'Cancel Trip',
|
||||
'Trip Cancelled'.tr,
|
||||
driverToken,
|
||||
[],
|
||||
'cancel.wav',
|
||||
);
|
||||
if (AppLink.endPoint != AppLink.seferCairoServer) {
|
||||
CRUD().post(
|
||||
link: "$AppLink.endPoint/ride/driver_order/update.php",
|
||||
payload: {
|
||||
"order_id": rideId.toString(), // Convert to String
|
||||
"status": 'Cancel'
|
||||
});
|
||||
}
|
||||
await CRUD().post(link: AppLink.updateRides, payload: {
|
||||
// if (rideConfirm == true ||
|
||||
// statusRide == 'Apply' ||
|
||||
// statusRide == 'Applied' ||
|
||||
// statusRide == 'wait' ||
|
||||
// statusRide == 'waiting') {
|
||||
clearPlacesDestination();
|
||||
clearPolyline();
|
||||
// clearPolylineAll();
|
||||
data = [];
|
||||
changeCancelRidePageShow();
|
||||
if (rideId != 'yet') {
|
||||
Log.print('cancelRide: 1');
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
'Cancel Trip'.tr,
|
||||
'Trip Cancelled'.tr,
|
||||
driverToken,
|
||||
[],
|
||||
'cancel.wav',
|
||||
);
|
||||
|
||||
await Future.wait([
|
||||
CRUD().post(link: AppLink.updateRides, payload: {
|
||||
"id": rideId.toString(), // Convert to String
|
||||
"status": 'Cancel'
|
||||
});
|
||||
if (AppLink.endPoint != AppLink.seferCairoServer) {
|
||||
CRUD().post(
|
||||
link: "${AppLink.endPoint}/ride/rides/update.php",
|
||||
payload: {
|
||||
"id": rideId.toString(), // Convert to String
|
||||
"status": 'Cancel'
|
||||
});
|
||||
}
|
||||
|
||||
}),
|
||||
CRUD().post(link: AppLink.updateDriverOrder, payload: {
|
||||
"order_id": rideId.toString(), // Convert to String
|
||||
"status": 'Cancel'
|
||||
}),
|
||||
CRUD().post(link: AppLink.updateWaitingTrip, payload: {
|
||||
"id": rideId.toString(), // Convert to String
|
||||
"status": 'Cancel'
|
||||
}),
|
||||
]);
|
||||
|
||||
if (AppLink.endPoint != AppLink.seferCairoServer) {
|
||||
CRUD().post(
|
||||
link: "${AppLink.endPoint}/ride/driver_order/update.php",
|
||||
payload: {
|
||||
"order_id": rideId.toString(), // Convert to String
|
||||
"status": 'Cancel'
|
||||
});
|
||||
CRUD()
|
||||
.post(link: "${AppLink.endPoint}/ride/rides/update.php", payload: {
|
||||
"id": rideId.toString(), // Convert to String
|
||||
"status": 'Cancel'
|
||||
});
|
||||
if (AppLink.endPoint != AppLink.seferCairoServer) {
|
||||
CRUD().post(
|
||||
link:
|
||||
"${AppLink.endPoint}/ride/notificationCaptain/updateWaitingTrip.php",
|
||||
payload: {
|
||||
"id": rideId.toString(), // Convert to String
|
||||
"status": 'Cancel'
|
||||
});
|
||||
}
|
||||
|
||||
print('Cancel');
|
||||
CRUD().post(
|
||||
link:
|
||||
"${AppLink.endPoint}/ride/notificationCaptain/updateWaitingTrip.php",
|
||||
payload: {
|
||||
"id": rideId.toString(), // Convert to String
|
||||
"status": 'Cancel'
|
||||
});
|
||||
}
|
||||
|
||||
Get.offAll(const MapPagePassenger());
|
||||
} else {
|
||||
clearPlacesDestination();
|
||||
clearPolyline();
|
||||
data = [];
|
||||
// await CRUD().post(link: AppLink.updateDriverOrder, payload: {
|
||||
// "order_id": rideId.toString(), // Convert to String
|
||||
// "status": 'Cancel'
|
||||
// });
|
||||
// await CRUD().post(link: AppLink.updateRides, payload: {
|
||||
// "id": rideId.toString(), // Convert to String
|
||||
// "status": 'Cancel'
|
||||
// });
|
||||
Get.offAll(const MapPagePassenger());
|
||||
print('Cancel');
|
||||
// }
|
||||
}
|
||||
Future.delayed(const Duration(seconds: 1));
|
||||
Get.offAll(() => const MapPagePassenger());
|
||||
}
|
||||
|
||||
void changePickerShown() {
|
||||
@@ -2942,28 +3309,28 @@ class MapPassengerController extends GetxController {
|
||||
? LatLng(_locationData.latitude!, _locationData.longitude!)
|
||||
: null)!;
|
||||
getLocationArea(passengerLocation.latitude, passengerLocation.longitude);
|
||||
Log.print('AppLink.endPoint: ${AppLink.endPoint}');
|
||||
// Log.print('BoxName.serverChosen: ${box.read(BoxName.serverChosen)}');
|
||||
|
||||
newStartPointLocation = passengerLocation;
|
||||
Log.print('passengerLocation: ${passengerLocation}');
|
||||
speed = _locationData.speed!;
|
||||
// //print location details
|
||||
isLoading = false;
|
||||
update();
|
||||
}
|
||||
|
||||
LatLngBounds calculateBounds(
|
||||
double centerLat, double centerLng, double radius) {
|
||||
// double radius = 4000; // 10 km in meters
|
||||
LatLngBounds calculateBounds(double lat, double lng, double radiusInMeters) {
|
||||
const double earthRadius = 6378137.0; // Earth's radius in meters
|
||||
|
||||
southwest = LatLng(
|
||||
centerLat - (radius / 111000),
|
||||
centerLng - (radius / (111000 * cos(centerLat))),
|
||||
double latDelta = radiusInMeters / earthRadius * (180 / pi);
|
||||
double lngDelta =
|
||||
radiusInMeters / (earthRadius * cos(pi * lat / 180)) * (180 / pi);
|
||||
|
||||
return LatLngBounds(
|
||||
southwest: LatLng(lat - latDelta, lng - lngDelta),
|
||||
northeast: LatLng(lat + latDelta, lng + lngDelta),
|
||||
);
|
||||
|
||||
northeast = LatLng(
|
||||
centerLat + (radius / 111000),
|
||||
centerLng + (radius / (111000 * cos(centerLat))),
|
||||
);
|
||||
|
||||
return LatLngBounds(southwest: southwest, northeast: northeast);
|
||||
}
|
||||
|
||||
GoogleMapController? mapController;
|
||||
@@ -2992,8 +3359,6 @@ class MapPassengerController extends GetxController {
|
||||
bool reloadStartApp = false;
|
||||
int reloadCount = 0;
|
||||
startMarkerReloading() async {
|
||||
Log.print('AppLink.endPoint: ${AppLink.endPoint}');
|
||||
|
||||
if (reloadStartApp == false) {
|
||||
Timer.periodic(const Duration(seconds: 5), (timer) async {
|
||||
reloadCount++;
|
||||
@@ -3233,7 +3598,7 @@ class MapPassengerController extends GetxController {
|
||||
remainingTime = 25; //to make cancel every call
|
||||
// startCarLocationSearch(box.read(BoxName.carType));
|
||||
await getCarsLocationByPassengerAndReloadMarker(
|
||||
box.read(BoxName.carType), 7000);
|
||||
box.read(BoxName.carType), 5000);
|
||||
// await getCarsLocationByPassengerAndReloadMarker();
|
||||
var coordDestination = destination.split(',');
|
||||
double latPassengerDestination = double.parse(coordDestination[0]);
|
||||
@@ -4093,55 +4458,77 @@ class MapPassengerController extends GetxController {
|
||||
try {
|
||||
// Prepare trip data
|
||||
Map<String, dynamic> tripData = {
|
||||
'id': driver['id'],
|
||||
'id': driver['id'].toString(), // Ensure the id is a string
|
||||
'phone': driver['phone'],
|
||||
'gender': driver['gender'],
|
||||
'name': driver['name'],
|
||||
'name': driver['NAME'],
|
||||
'name_english': driver['name_english'],
|
||||
'address': driver['address'],
|
||||
'religion': driver['religion'],
|
||||
'age': driver['age'],
|
||||
'age': driver['age'].toString(), // Convert age to String
|
||||
'education': driver['education'],
|
||||
'license_type': driver['license_type'],
|
||||
'national_number': driver['national_number'],
|
||||
'car_plate': driver['car_plate'],
|
||||
'make': driver['make'],
|
||||
'model': driver['model'],
|
||||
'year': driver['year'],
|
||||
'year': driver['year'].toString(), // Convert year to String
|
||||
'color': driver['color'],
|
||||
'color_hex': driver['color_hex'],
|
||||
'displacement': driver['displacement'],
|
||||
'fuel': driver['fuel'],
|
||||
'token': driver['token'],
|
||||
'rating': driver['rating'],
|
||||
'countRide': driver['countRide'],
|
||||
'rating': driver['rating'].toString(), // Convert rating to String
|
||||
'countRide':
|
||||
driver['countRide'].toString(), // Convert countRide to String
|
||||
'passengerId': box.read(BoxName.passengerID),
|
||||
'timeSelected': tripDateTime.toIso8601String(),
|
||||
'status': 'pending', // Or other appropriate status
|
||||
'status': 'pending',
|
||||
};
|
||||
// Log.print('tripData: $tripData');
|
||||
|
||||
// Send data to server
|
||||
var response =
|
||||
await CRUD().post(link: AppLink.addMishwari, payload: tripData);
|
||||
// Log.print('response: $response');
|
||||
|
||||
if (response != 'failure') {
|
||||
// Trip saved successfully
|
||||
Get.snackbar('Success'.tr, 'Trip booked successfully'.tr);
|
||||
var id = response['message'].toString();
|
||||
if (AppLink.endPoint != AppLink.seferCairoServer) {
|
||||
CRUD().post(
|
||||
await CRUD().post(
|
||||
link: "${AppLink.endPoint}/ride/mishwari/add.php",
|
||||
payload: tripData);
|
||||
}
|
||||
// Set up local notification
|
||||
// Optionally, set up local notification or send a push notification
|
||||
// await setLocalNotification(tripDateTime);
|
||||
|
||||
// Send notification to driver
|
||||
// await FirebaseMessagesController().sendNotificationToDriverMAP();
|
||||
await FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
'OrderVIP',
|
||||
rideId.toString(),
|
||||
driver['token'].toString(),
|
||||
[
|
||||
id,
|
||||
driver['id'],
|
||||
passengerLocation.latitude.toString(),
|
||||
passengerLocation.longitude.toString(),
|
||||
box.read(BoxName.name).toString(),
|
||||
box.read(BoxName.passengerID).toString(),
|
||||
box.read(BoxName.phone).toString(),
|
||||
box.read(BoxName.email).toString(),
|
||||
box.read(BoxName.passengerPhotoUrl).toString(),
|
||||
box.read(BoxName.tokenFCM).toString(),
|
||||
driver['token'].toString(),
|
||||
],
|
||||
'order.wav');
|
||||
} else {
|
||||
throw Exception('Failed to save trip');
|
||||
}
|
||||
} catch (e) {
|
||||
Get.snackbar('Error'.tr, 'Failed to book trip: $e'.tr);
|
||||
// Show error message with more details for debugging
|
||||
Get.snackbar('Error'.tr, 'Failed to book trip: $e'.tr,
|
||||
backgroundColor: AppColor.redColor);
|
||||
Log.print('Error: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4253,8 +4640,8 @@ class MapPassengerController extends GetxController {
|
||||
addCustomStepIcon();
|
||||
addCustomStartIcon();
|
||||
addCustomEndIcon();
|
||||
addToken();
|
||||
getLocation();
|
||||
// addToken();
|
||||
await getLocation();
|
||||
getPassengerLocationUniversity();
|
||||
_initializePolygons();
|
||||
// await addToken();
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:SEFER/views/widgets/my_dialog.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:SEFER/constant/box_name.dart';
|
||||
import 'package:SEFER/constant/colors.dart';
|
||||
import 'package:SEFER/constant/links.dart';
|
||||
@@ -9,11 +12,38 @@ import 'package:SEFER/constant/style.dart';
|
||||
import 'package:SEFER/controller/functions/crud.dart';
|
||||
import 'package:SEFER/main.dart';
|
||||
import 'package:SEFER/views/widgets/elevated_btn.dart';
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
import 'package:mime/mime.dart';
|
||||
|
||||
import '../../../constant/api_key.dart';
|
||||
import '../../../print.dart';
|
||||
|
||||
class ComplaintController extends GetxController {
|
||||
bool isLoading = false;
|
||||
final formKey = GlobalKey<FormState>();
|
||||
final complaintController = TextEditingController();
|
||||
final suggestionController = TextEditingController();
|
||||
List feedBack = [];
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
getLatestRidesForPassengers();
|
||||
}
|
||||
|
||||
getLatestRidesForPassengers() async {
|
||||
isLoading = true;
|
||||
update();
|
||||
var res = await CRUD().get(link: AppLink.getFeedBack, payload: {
|
||||
'passengerId': box.read(BoxName.passengerID).toString(),
|
||||
});
|
||||
if (res != 'failure') {
|
||||
var d = jsonDecode(res)['message'];
|
||||
feedBack = d;
|
||||
}
|
||||
|
||||
isLoading = false;
|
||||
update();
|
||||
}
|
||||
|
||||
void addComplaint() async {
|
||||
isLoading = true;
|
||||
@@ -34,11 +64,175 @@ class ComplaintController extends GetxController {
|
||||
title: 'Ok'.tr,
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
Get.back();
|
||||
// Get.back();
|
||||
}));
|
||||
}
|
||||
|
||||
isLoading = false;
|
||||
update();
|
||||
}
|
||||
|
||||
var isUploading = false.obs;
|
||||
var uploadSuccess = false.obs;
|
||||
late String audioLink = '';
|
||||
Future<void> uploadAudioFile(File audioFile) async {
|
||||
try {
|
||||
isUploading.value = true;
|
||||
|
||||
// Prepare the file upload
|
||||
var uri = Uri.parse('${AppLink.seferCairoServer}/upload_audio.php');
|
||||
var request = http.MultipartRequest('POST', uri);
|
||||
|
||||
// Add the file to the request with MIME type
|
||||
var mimeType = lookupMimeType(audioFile.path);
|
||||
request.headers.addAll({
|
||||
'Authorization':
|
||||
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}',
|
||||
});
|
||||
request.files.add(
|
||||
await http.MultipartFile.fromPath(
|
||||
'audio',
|
||||
audioFile.path,
|
||||
contentType: mimeType != null ? MediaType.parse(mimeType) : null,
|
||||
),
|
||||
);
|
||||
|
||||
// Send the request
|
||||
var response = await request.send();
|
||||
|
||||
// Convert response to string for parsing
|
||||
var responseBody = await http.Response.fromStream(response);
|
||||
|
||||
// After the upload request
|
||||
if (response.statusCode == 200) {
|
||||
var jsonResponse = jsonDecode(responseBody.body);
|
||||
|
||||
if (jsonResponse['status'] == 'Audio file uploaded successfully.') {
|
||||
uploadSuccess.value = true;
|
||||
audioLink = jsonResponse['link']; // Get the audio link
|
||||
Get.back();
|
||||
Get.snackbar('Success'.tr, 'Audio uploaded successfully.'.tr,
|
||||
backgroundColor: const Color.fromARGB(255, 89, 185, 115));
|
||||
} else {
|
||||
uploadSuccess.value = false;
|
||||
}
|
||||
} else {
|
||||
uploadSuccess.value = false;
|
||||
}
|
||||
} catch (e) {
|
||||
uploadSuccess.value = false;
|
||||
} finally {
|
||||
isUploading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
var customerServiceSolutions;
|
||||
var passengerReport;
|
||||
var driverReport;
|
||||
var isloading = false;
|
||||
Future<void> geminiAudio(payload, String audioLink, String complain) async {
|
||||
String prompt = '''
|
||||
Analyze the following complaint between a passenger and driver in a ride-hailing service. The complaint includes an audio link for reference. Provide two possible solutions for customer service to resolve the issue, and generate a detailed report for both the passenger and the driver.
|
||||
|
||||
Complaint details:
|
||||
- Passenger: $complain
|
||||
- Driver: [Driver's complaint]
|
||||
- Ride Information: {ride details such as start_location, end_location, date, price, status, and rating details}
|
||||
- Audio Link: [$audioLink]
|
||||
|
||||
Output the result in JSON format with the following structure:
|
||||
{
|
||||
"customerServiceSolutions": [
|
||||
"solution1",
|
||||
"solution2"
|
||||
],
|
||||
"passengerReport": {
|
||||
"solution": "Passenger's solution" if passenger right,
|
||||
"complaint": "Passenger's complaint",
|
||||
"rideDetails": {detailed ride info}
|
||||
},
|
||||
"driverReport": {
|
||||
"complaint": "Driver's complaint",
|
||||
"rideDetails": {detailed ride info}
|
||||
}
|
||||
} the response in arabic language with egypt
|
||||
''';
|
||||
|
||||
var requestBody = jsonEncode({
|
||||
"contents": [
|
||||
{
|
||||
"parts": [
|
||||
{"text": "$payload $prompt"}
|
||||
]
|
||||
}
|
||||
],
|
||||
"generationConfig": {
|
||||
"temperature": 1,
|
||||
"topK": 64,
|
||||
"topP": 0.95,
|
||||
"maxOutputTokens": 8192,
|
||||
"stopSequences": []
|
||||
},
|
||||
"safetySettings": [
|
||||
{
|
||||
"category": "HARM_CATEGORY_HARASSMENT",
|
||||
"threshold": "BLOCK_MEDIUM_AND_ABOVE"
|
||||
},
|
||||
{
|
||||
"category": "HARM_CATEGORY_HATE_SPEECH",
|
||||
"threshold": "BLOCK_MEDIUM_AND_ABOVE"
|
||||
},
|
||||
{
|
||||
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
|
||||
"threshold": "BLOCK_MEDIUM_AND_ABOVE"
|
||||
},
|
||||
{
|
||||
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
|
||||
"threshold": "BLOCK_MEDIUM_AND_ABOVE"
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
final response = await http.post(
|
||||
Uri.parse(
|
||||
'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.0-pro:generateContent?key=${AK.geminiApi}'),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: requestBody,
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
var responseData = jsonDecode(response.body);
|
||||
var result = responseData['candidates'][0]['content']['parts'][0]['text'];
|
||||
Log.print('result: ${result}');
|
||||
|
||||
// Clean up the result by removing surrounding backticks if they exist
|
||||
result = result.replaceAll(RegExp(r'^```json\s*|\s*```$'), '');
|
||||
|
||||
// Attempt to decode the cleaned result as JSON
|
||||
try {
|
||||
var jsonResult = jsonDecode(result);
|
||||
|
||||
// Access customer service solutions and reports for both passenger and driver
|
||||
customerServiceSolutions = jsonResult['customerServiceSolutions'];
|
||||
passengerReport = jsonResult['passengerReport'];
|
||||
driverReport = jsonResult['driverReport'];
|
||||
update();
|
||||
// Use the data accordingly
|
||||
// For example, log the reports or display them in a UI dialog
|
||||
|
||||
update();
|
||||
} catch (e) {
|
||||
MyDialog().getDialog(
|
||||
'Error'.tr,
|
||||
'Unable to parse the response as JSON. Please check the format and try again.'
|
||||
.tr, () {
|
||||
Get.back();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Get.snackbar(
|
||||
'Error', "Request failed with status: ${response.statusCode}",
|
||||
backgroundColor: AppColor.redColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
280
lib/controller/home/profile/invit_controller.dart
Normal file
280
lib/controller/home/profile/invit_controller.dart
Normal file
@@ -0,0 +1,280 @@
|
||||
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/controller/home/payment/captain_wallet_controller.dart';
|
||||
import 'package:SEFER/controller/payment/payment_controller.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_contacts/contact.dart';
|
||||
import 'package:flutter_contacts/flutter_contacts.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:share/share.dart';
|
||||
|
||||
import '../../../main.dart';
|
||||
import '../../../views/widgets/my_dialog.dart';
|
||||
import '../../functions/launch.dart';
|
||||
import '../../notification/notification_captain_controller.dart';
|
||||
|
||||
class InviteController extends GetxController {
|
||||
final TextEditingController invitePhoneController = TextEditingController();
|
||||
List driverInvitationData = [];
|
||||
List driverInvitationDataToPassengers = [];
|
||||
String? couponCode;
|
||||
String? driverCouponCode;
|
||||
|
||||
int selectedTab = 0;
|
||||
PassengerStats passengerStats = PassengerStats();
|
||||
void updateSelectedTab(int index) {
|
||||
selectedTab = index;
|
||||
update();
|
||||
}
|
||||
|
||||
Future<void> shareCouponCode() async {
|
||||
// TODO: Implement sharing functionality
|
||||
// You can use share_plus package to share the coupon code
|
||||
}
|
||||
Future<void> shareDriverCode() async {
|
||||
if (driverCouponCode != null) {
|
||||
final String shareText = '''
|
||||
Join SEFER as a driver using my referral code!
|
||||
Use code: $driverCouponCode
|
||||
Download the SEFER Driver app now and earn rewards!
|
||||
''';
|
||||
await Share.share(shareText);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> sharePassengerCode() async {
|
||||
if (couponCode != null) {
|
||||
final String shareText = '''
|
||||
Get a discount on your first SEFER ride!
|
||||
Use my referral code: $couponCode
|
||||
Download the SEFER app now and enjoy your ride!
|
||||
''';
|
||||
await Share.share(shareText);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
// fetchDriverStats();
|
||||
}
|
||||
|
||||
void fetchDriverStats() async {
|
||||
try {
|
||||
var response = await CRUD().get(link: AppLink.getInviteDriver, payload: {
|
||||
"driverId": box.read(BoxName.driverID),
|
||||
});
|
||||
if (response != 'failure') {
|
||||
var data = jsonDecode(response);
|
||||
driverInvitationData = data['message'];
|
||||
update();
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
void fetchDriverStatsPassengers() async {
|
||||
try {
|
||||
var response = await CRUD()
|
||||
.get(link: AppLink.getDriverInvitationToPassengers, payload: {
|
||||
"driverId": box.read(BoxName.passengerID),
|
||||
});
|
||||
if (response != 'failure') {
|
||||
var data = jsonDecode(response);
|
||||
driverInvitationDataToPassengers = data['message'];
|
||||
update();
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
void selectPhone(String phone) {
|
||||
if (box.read(BoxName.countryCode) == 'Egypt') {
|
||||
invitePhoneController.text = phone;
|
||||
update();
|
||||
Get.back();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> saveContactsToServer() async {
|
||||
try {
|
||||
// TODO: Implement the actual server upload logic here
|
||||
// Simulating a server request
|
||||
await Future.delayed(Duration(seconds: 2));
|
||||
Get.snackbar('Success'.tr,
|
||||
'${selectedContacts.length} contacts saved to server'.tr);
|
||||
} catch (e) {
|
||||
Get.snackbar('Error'.tr,
|
||||
'An error occurred while saving contacts to server: $e'.tr);
|
||||
}
|
||||
}
|
||||
|
||||
List<Contact> contacts = <Contact>[];
|
||||
List<Contact> selectedContacts = <Contact>[];
|
||||
RxList<Map<String, dynamic>> contactMaps = <Map<String, dynamic>>[].obs;
|
||||
|
||||
Future<void> pickContacts() async {
|
||||
try {
|
||||
if (await FlutterContacts.requestPermission(readonly: true)) {
|
||||
final List<Contact> fetchedContacts =
|
||||
await FlutterContacts.getContacts(withProperties: true);
|
||||
contacts = fetchedContacts;
|
||||
|
||||
// Convert contacts to a list of maps
|
||||
contactMaps.value = fetchedContacts.map((contact) {
|
||||
return {
|
||||
'name': contact.displayName,
|
||||
'phones':
|
||||
contact.phones.map((phone) => phone.normalizedNumber).toList(),
|
||||
'emails': contact.emails.map((email) => email.address).toList(),
|
||||
};
|
||||
}).toList();
|
||||
update();
|
||||
|
||||
if (contacts.isEmpty) {
|
||||
Get.snackbar('No contacts available'.tr,
|
||||
'Please add contacts to your phone.'.tr);
|
||||
}
|
||||
} else {
|
||||
Get.snackbar('Permission denied'.tr,
|
||||
'Contact permission is required to pick contacts'.tr);
|
||||
}
|
||||
} catch (e) {
|
||||
Get.snackbar(
|
||||
'Error'.tr, 'An error occurred while picking contacts: $e'.tr);
|
||||
}
|
||||
}
|
||||
|
||||
void onSelectPassengerInvitation(int index) async {
|
||||
MyDialog().getDialog(
|
||||
driverInvitationDataToPassengers[index]['countOfInvitDriver'] < 2
|
||||
? '${'When'.tr} ${driverInvitationDataToPassengers[index]['passengerName']} ${"complete, you can claim your gift".tr} '
|
||||
: 'You deserve the gift'.tr,
|
||||
'${driverInvitationDataToPassengers[index]['passengerName']} ${driverInvitationDataToPassengers[index]['countOfInvitDriver']} / 2 ${'Trip'.tr}',
|
||||
() async {
|
||||
if (driverInvitationDataToPassengers[index]['countOfInvitDriver'] < 2) {
|
||||
Get.back();
|
||||
} else {
|
||||
// Claim the gift if 100 trips are completed
|
||||
if (driverInvitationDataToPassengers[index]['isGiftToken']
|
||||
.toString() ==
|
||||
'0') {
|
||||
Get.back();
|
||||
// Add wallet to the inviter
|
||||
await Get.find<PaymentController>().addPassengersWallet('20');
|
||||
// add for invitor too
|
||||
// await Get.find<CaptainWalletController>().addDriverWalletToInvitor(
|
||||
// 'paymentMethod',
|
||||
// driverInvitationData[index]['driverInviterId'],
|
||||
// '50');
|
||||
// Update invitation as claimed
|
||||
await CRUD().post(
|
||||
link: AppLink.updatePassengerGift,
|
||||
payload: {'id': driverInvitationDataToPassengers[index]['id']},
|
||||
);
|
||||
// Notify the inviter
|
||||
NotificationCaptainController().addNotificationCaptain(
|
||||
driverInvitationDataToPassengers[index]['passengerInviterId']
|
||||
.toString(),
|
||||
"You have got a gift for invitation".tr,
|
||||
'${"You have 20".tr} ${'LE'}',
|
||||
false,
|
||||
);
|
||||
} else {
|
||||
Get.back();
|
||||
MyDialog().getDialog(
|
||||
"You have got a gift".tr,
|
||||
"Share the app with another new passenger".tr,
|
||||
() {
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
savePhoneToServer() async {
|
||||
for (var i = 0; i < contactMaps.length; i++) {
|
||||
var phones = contactMaps[i]['phones'];
|
||||
if (phones != null && phones.isNotEmpty && phones[0].isNotEmpty) {
|
||||
var res = await CRUD().post(link: AppLink.savePhones, payload: {
|
||||
"name": contactMaps[i]['name'] ?? 'none',
|
||||
"phones": phones[0] ?? 'none',
|
||||
"phones2": phones.join(', ') ??
|
||||
'none', // Convert List<String> to a comma-separated string
|
||||
});
|
||||
if (res != 'failure') {}
|
||||
} else {}
|
||||
}
|
||||
}
|
||||
|
||||
String formatPhoneNumber(String input) {
|
||||
// Remove any non-digit characters
|
||||
String digitsOnly = input.replaceAll(RegExp(r'\D'), '');
|
||||
|
||||
// Ensure the number starts with the country code
|
||||
if (digitsOnly.startsWith('20')) {
|
||||
digitsOnly = digitsOnly.substring(1);
|
||||
}
|
||||
|
||||
return digitsOnly;
|
||||
}
|
||||
|
||||
void sendInviteToPassenger() async {
|
||||
if (invitePhoneController.text.isEmpty) {
|
||||
Get.snackbar('Error', 'Please enter an phone address'.tr);
|
||||
return;
|
||||
}
|
||||
|
||||
// try {
|
||||
String phoneNumber = formatPhoneNumber(invitePhoneController.text);
|
||||
|
||||
var response =
|
||||
await CRUD().post(link: AppLink.addInvitationPassenger, payload: {
|
||||
"driverId": box.read(BoxName.passengerID),
|
||||
"inviterPassengerPhone": '+2$phoneNumber'
|
||||
});
|
||||
|
||||
if (response != 'failure') {
|
||||
var d = jsonDecode(response);
|
||||
Get.snackbar('Success', 'Invite sent successfully'.tr);
|
||||
|
||||
String message = '${'*SEFER APP CODE*'.tr}\n\n'
|
||||
'${"Use this code in registration".tr}\n'
|
||||
'${"To get a gift for both".tr}\n\n'
|
||||
'${"The period of this code is 1 hour".tr}\n\n'
|
||||
'${'before'.tr} *${d['message']['expirationTime'].toString()}*\n\n'
|
||||
'_*${d['message']['inviteCode'].toString()}*_\n\n'
|
||||
'${"Install our app:".tr}\n'
|
||||
'*Android:* https://play.google.com/store/apps/details?id=com.mobileapp.store.ride\n\n\n'
|
||||
'*iOS:* https://apps.apple.com/us/app/sefer/id6458734951';
|
||||
|
||||
launchCommunication('whatsapp', '+2$phoneNumber', message);
|
||||
|
||||
invitePhoneController.clear();
|
||||
} else {
|
||||
Get.snackbar('Error'.tr, "Invite code already used".tr,
|
||||
backgroundColor: AppColor.redColor,
|
||||
duration: const Duration(seconds: 4));
|
||||
}
|
||||
// } catch (e) {
|
||||
// Get.snackbar('Error', 'An error occurred'.tr);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
class PassengerStats {
|
||||
final int totalInvites;
|
||||
final int activeUsers;
|
||||
final double totalEarnings;
|
||||
|
||||
PassengerStats({
|
||||
this.totalInvites = 0,
|
||||
this.activeUsers = 0,
|
||||
this.totalEarnings = 0.0,
|
||||
});
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:SEFER/constant/box_name.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:SEFER/constant/links.dart';
|
||||
import 'package:SEFER/constant/style.dart';
|
||||
import 'package:SEFER/controller/functions/crud.dart';
|
||||
import 'package:SEFER/views/widgets/elevated_btn.dart';
|
||||
|
||||
import '../../../main.dart';
|
||||
|
||||
class PromosController extends GetxController {
|
||||
List<dynamic> promoList = [];
|
||||
@@ -17,7 +18,9 @@ class PromosController extends GetxController {
|
||||
}
|
||||
|
||||
Future getPromoByToday() async {
|
||||
var res = await CRUD().get(link: AppLink.getPromoBytody, payload: {});
|
||||
var res = await CRUD().get(link: AppLink.getPromoBytody, payload: {
|
||||
'passengerID': box.read(BoxName.passengerID).toString(),
|
||||
});
|
||||
if (res.toString() == 'failure') {
|
||||
// Get.defaultDialog(
|
||||
// title: 'No Promo for today .'.tr,
|
||||
|
||||
@@ -94,7 +94,7 @@ class LocaleController extends GetxController {
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
String storedLang = box.read(BoxName.lang) ?? "";
|
||||
String storedLang = box.read(BoxName.lang) ?? "ar";
|
||||
switch (storedLang) {
|
||||
case "ar":
|
||||
language = const Locale("ar");
|
||||
|
||||
@@ -56,8 +56,7 @@ class MyTranslation extends Translations {
|
||||
"I want to order for someone else": "أريد أن أطلب لشخص آخر",
|
||||
"Cancel Trip from driver": "إلغاء الرحلة من السائق",
|
||||
"If you want order to another person": "إذا كنت تريد الطلب لشخص آخر",
|
||||
"We will look for a new driver.\nPlease wait.":
|
||||
"سنبحث عن سائق جديد.\nمن فضلك انتظر.",
|
||||
|
||||
"upgrade price": "رفع السعر",
|
||||
'airport': 'مطار',
|
||||
"Best choice for a comfortable car with a flexible route and stop points. This airport offers visa entry at this price.":
|
||||
@@ -234,15 +233,76 @@ iOS [https://getapp.cc/app/6458734951]
|
||||
"Capture an Image of Your ID Document front":
|
||||
"التقط صورة للواجهة الأمامية لوثيقة هويتك",
|
||||
"NationalID": "الرقم القومي",
|
||||
'You can share the SEFER App with your friends and earn rewards for rides they take using your code':
|
||||
'يمكنك مشاركة تطبيق SEFER مع أصدقائك وكسب مكافآت من الرحلات التي يقومون بها باستخدام كودك.',
|
||||
"FullName": "الاسم الكامل",
|
||||
"No invitation found yet!": "لم يتم العثور على دعوات حتى الآن!",
|
||||
"InspectionResult": "نتيجة الفحص",
|
||||
"Criminal Record": "السجل الجنائي",
|
||||
"Criminal Record": "السجل الجنائي", 'Share App': 'شارك التطبيق',
|
||||
"The email or phone number is already registered.":
|
||||
"البريد الإلكتروني أو رقم الهاتف مسجل بالفعل.",
|
||||
'To become a ride-sharing driver on the Sefer app, you need to upload your driver\'s license, ID document, and car registration document. Our AI system will instantly review and verify their authenticity in just 2-3 minutes. If your documents are approved, you can start working as a driver on the Sefer app. Please note, submitting fraudulent documents is a serious offense and may result in immediate termination and legal consequences.':
|
||||
'لِتُصْبِحَ سَائِقَاً لِلرُّكوبِ المُشْتَرَكِ عَلَى تَطْبِيق سَفَر، يَجِبُ عَلَيْكَ تَحْمِيل رُخْصَةِ القِيَادَةِ، وَثِيقَةِ الهُوِيَّةِ، وَوَثِيقَةَ تَسْجِيل السَّيَّارَةِ. سَيَقُومُ نِظَامُ الذَّكَاءِ الاِصْطِنَاعِيِّ لَدَيْنَا بِمُرَاجَعَةِ وَتَحْقِيقِ صِحَّةِ الوَثَائِقِ فِي غُضُونِ ٢-٣ دَقَائِقَ فَقَطْ. إِذَا تَمَّتْ المُوَافَقَةُ عَلَى وَثَائِقِكَ، يُمْكِنُكَ البَدْءُ فِي العَمَلِ كَسَائِقٍ عَلَى تَطْبِيق سَفَر. يُرْجَى مُلَاحَظَةُ، تَقْدِيمُ وَثَائِقَ مُزَورَةٍ يُعَدُّ جَرِيمَةً خَطِيرَةً وَقَدْ يَتَرَتَّبُ عَلَيْهِ اِنهَاءُ الحِسَابِ فَوْرِيَّاً وَعَوَاقِبُ قَانُونِيَّة.',
|
||||
"Documents check": "فحص الوثائق",
|
||||
"Driver's License": "رخصة القيادة",
|
||||
|
||||
"for your first registration!": "للتسجيل الأول!",
|
||||
"Get it Now!": "احصل عليه الآن!",
|
||||
"before": "قبل",
|
||||
"Code not approved": "الرمز غير موافق عليه",
|
||||
"3000 LE": "3000 جنيه مصري",
|
||||
"Do you have an invitation code from another driver?":
|
||||
"هل لديك كود دعوة من سائق آخر؟",
|
||||
"Paste the code here": "الصق الكود هنا",
|
||||
"No, I don't have a code": "لا، لا أملك كودا",
|
||||
"Code approved": "تمت الموافقة على الكود",
|
||||
"Install our app:": "قم بتثبيت تطبيقنا:",
|
||||
"Invite another driver and both get a gift after he completes 100 trips!":
|
||||
"ادع صديقًا ليكون سائقًا واحصلا على هدية بعد إكماله 100 مشوار!",
|
||||
"Share App": "شارك التطبيق",
|
||||
"Invite": "دعوة", "Are you sure?": "هل أنت متأكد؟",
|
||||
"This will delete all recorded files from your device.":
|
||||
"سيؤدي هذا إلى حذف جميع الملفات المسجلة من جهازك.",
|
||||
"Select a file": "اختر ملفاً",
|
||||
"Select a File": "اختر ملفاً", "Delete": "حذف",
|
||||
'attach audio of complain': 'إرفاق صوت للشكوى',
|
||||
"Phone Number Check": "فحص رقم الهاتف",
|
||||
"Drivers received orders": "السائقون استقبلوا الطلبات",
|
||||
'No audio files recorded.': 'لا توجد ملفات صوتية مسجلة.',
|
||||
'This is for delivery or a motorcycle.':
|
||||
"هذا للتوصيل أو للدراجة النارية.",
|
||||
"We will look for a new driver.\nPlease wait.":
|
||||
"سوف نبحث عن سائق جديد.\nيرجى الانتظار",
|
||||
"Sefer Reminder": "تطبيق سفر",
|
||||
"It's time to check the Sefer app!": "حان وقت استخدام تطبيق سفر",
|
||||
"The email or phone number is already registered.":
|
||||
"البريد الإلكتروني أو رقم الهاتف مسجل بالفعل.",
|
||||
"you must insert token code": "يجب إدخال رمز التحقق.",
|
||||
"Something went wrong. Please try again.":
|
||||
"حدث خطأ ما. يرجى المحاولة مرة أخرى.",
|
||||
"This is for delivery or a motorcycle.":
|
||||
"هذا للتوصيل أو للدراجة النارية.",
|
||||
"Trip Details": "تفاصيل الرحلة",
|
||||
'The context does not provide any complaint details, so I cannot provide a solution to this issue. Please provide the necessary information, and I will be happy to assist you.':
|
||||
"لا تتوفر تفاصيل الشكوى في السياق، لذا لا أستطيع تقديم حل لهذه المشكلة. يرجى تقديم المعلومات اللازمة، وسأكون سعيدًا بمساعدتك",
|
||||
'Submit Your Complaint': "أرسل شكواك",
|
||||
"Date": "التاريخ",
|
||||
"Price": "السعر",
|
||||
"Status": "الحالة",
|
||||
"Choose from contact": "اختر من جهات الاتصال",
|
||||
'attach correct audio': "إرفاق صوت للشكوى",
|
||||
'be sure': 'كن متأكدًا',
|
||||
'Audio uploaded successfully.': 'تم رفع الصوت بنجاح',
|
||||
"Perfect for passengers seeking the latest car models with the freedom to choose any route they desire":
|
||||
"مثالي للركاب الذين يبحثون عن أحدث موديلات السيارات مع حرية اختيار أي طريق يرغبون به",
|
||||
"Share this code with your friends and earn rewards when they use it!":
|
||||
"شارك هذا الرمز مع أصدقائك واحصل على مكافآت عند استخدامهم له!",
|
||||
"Enter phone": "أدخل رقم الهاتف",
|
||||
'You deserve the gift': "أنت تستحق الهدية",
|
||||
"complete, you can claim your gift": " يمكنك المطالبة بهديتك",
|
||||
"When": "عندما يكمل",
|
||||
"Enter driver's phone": "أدخل رقم هاتف السائق",
|
||||
"Send Invite": "أرسل الدعوة", "Show Invitations": "عرض الدعوات",
|
||||
"License Type": "نوع الرخصة",
|
||||
"National Number": "الرقم الوطني",
|
||||
"Name (Arabic)": "الاسم بالعربي",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:SEFER/constant/colors.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:SEFER/constant/box_name.dart';
|
||||
@@ -48,40 +50,41 @@ class ProfileController extends GetxController {
|
||||
}
|
||||
|
||||
updatField(String columnName, TextInputType type) async {
|
||||
Get.defaultDialog(
|
||||
title: '${'Update'.tr} $columnName',
|
||||
content: Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: Get.width * .7,
|
||||
child: MyTextForm(
|
||||
controller: txtController,
|
||||
label: 'type here'.tr,
|
||||
hint: 'type here',
|
||||
type: type)
|
||||
// TextField(
|
||||
// controller: txtController,
|
||||
// decoration: const InputDecoration(
|
||||
// border: OutlineInputBorder(), hintText: 'type here'),
|
||||
// ),
|
||||
|
||||
Get.dialog(
|
||||
CupertinoAlertDialog(
|
||||
title: Text('${'Update'.tr} $columnName'),
|
||||
content: Column(
|
||||
children: [
|
||||
const SizedBox(height: 16), // Add spacing between title and input
|
||||
CupertinoTextField(
|
||||
controller: txtController,
|
||||
placeholder: 'type here'.tr,
|
||||
keyboardType: type,
|
||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: CupertinoColors.lightBackgroundGray),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
MyElevatedButton(
|
||||
title: 'Update'.tr,
|
||||
onPressed: () async {
|
||||
Get.back();
|
||||
await updateColumn({
|
||||
'id': box.read(BoxName.passengerID),
|
||||
columnName: txtController.text,
|
||||
});
|
||||
if (columnName == 'first_name') {
|
||||
box.write(BoxName.name, txtController.text);
|
||||
}
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
CupertinoButton(
|
||||
color: AppColor.blueColor,
|
||||
onPressed: () async {
|
||||
Get.back();
|
||||
await updateColumn({
|
||||
'id': box.read(BoxName.passengerID),
|
||||
columnName: txtController.text,
|
||||
});
|
||||
if (columnName == 'first_name') {
|
||||
box.write(BoxName.name, txtController.text);
|
||||
}
|
||||
|
||||
txtController.clear();
|
||||
},
|
||||
)
|
||||
],
|
||||
txtController.clear();
|
||||
},
|
||||
child: Text('Update'.tr),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -70,10 +70,11 @@ class RateController extends GetxController {
|
||||
'token': token1,
|
||||
});
|
||||
if (res != 'failure') {
|
||||
FirebaseMessagesController().sendNotificationToAnyWithoutData(
|
||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||
'You Have Tips'.tr,
|
||||
'${'${tip.toString()}\$${' tips\nTotal is'.tr}'} ${tip + (Get.find<MapPassengerController>().totalPassenger)}',
|
||||
Get.find<MapPassengerController>().driverToken.toString(),
|
||||
[],
|
||||
'ding.wav',
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user