11/9/1
This commit is contained in:
@@ -148,8 +148,8 @@ android {
|
|||||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
|
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
|
||||||
minSdk = 23
|
minSdk = 23
|
||||||
targetSdk = flutter.targetSdkVersion
|
targetSdk = flutter.targetSdkVersion
|
||||||
versionCode = 82
|
versionCode = 93
|
||||||
versionName = '1.5.82'
|
versionName = '1.5.93'
|
||||||
multiDexEnabled =true
|
multiDexEnabled =true
|
||||||
|
|
||||||
// manifestPlaceholders can be specified here if needed
|
// manifestPlaceholders can be specified here if needed
|
||||||
|
|||||||
@@ -10,6 +10,12 @@
|
|||||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
||||||
|
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
|
<uses-permission android:name="android.permission.QUICKBOOT_POWERON" />
|
||||||
|
<uses-permission android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
|
||||||
|
|
||||||
<uses-feature android:name="android.hardware.camera" />
|
<uses-feature android:name="android.hardware.camera" />
|
||||||
<uses-feature android:name="android.hardware.camera.autofocus" />
|
<uses-feature android:name="android.hardware.camera.autofocus" />
|
||||||
@@ -59,6 +65,17 @@
|
|||||||
<meta-data
|
<meta-data
|
||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
|
<receiver android:exported="false"
|
||||||
|
android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
|
||||||
|
<receiver android:exported="false"
|
||||||
|
android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
|
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||||
|
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
|
||||||
|
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
<activity
|
<activity
|
||||||
android:name="com.yalantis.ucrop.UCropActivity"
|
android:name="com.yalantis.ucrop.UCropActivity"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ PODS:
|
|||||||
- GoogleUtilities/UserDefaults (~> 8.0)
|
- GoogleUtilities/UserDefaults (~> 8.0)
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
|
- flutter_contacts (0.0.1):
|
||||||
|
- Flutter
|
||||||
- flutter_local_notifications (0.0.1):
|
- flutter_local_notifications (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_secure_storage (6.0.0):
|
- flutter_secure_storage (6.0.0):
|
||||||
@@ -221,6 +223,7 @@ DEPENDENCIES:
|
|||||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||||
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
|
- flutter_contacts (from `.symlinks/plugins/flutter_contacts/ios`)
|
||||||
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||||
- flutter_tts (from `.symlinks/plugins/flutter_tts/ios`)
|
- flutter_tts (from `.symlinks/plugins/flutter_tts/ios`)
|
||||||
@@ -292,6 +295,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/firebase_messaging/ios"
|
:path: ".symlinks/plugins/firebase_messaging/ios"
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: Flutter
|
:path: Flutter
|
||||||
|
flutter_contacts:
|
||||||
|
:path: ".symlinks/plugins/flutter_contacts/ios"
|
||||||
flutter_local_notifications:
|
flutter_local_notifications:
|
||||||
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
||||||
flutter_secure_storage:
|
flutter_secure_storage:
|
||||||
@@ -360,6 +365,7 @@ SPEC CHECKSUMS:
|
|||||||
FirebaseInstallations: 771177d89d6c451dc6e50085ec82e2fc77ed0a4a
|
FirebaseInstallations: 771177d89d6c451dc6e50085ec82e2fc77ed0a4a
|
||||||
FirebaseMessaging: d2d1d9c62c46dd2db49a952f7deb5b16ad2c9742
|
FirebaseMessaging: d2d1d9c62c46dd2db49a952f7deb5b16ad2c9742
|
||||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||||
|
flutter_contacts: edb1c5ce76aa433e20e6cb14c615f4c0b66e0983
|
||||||
flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
|
flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086
|
||||||
flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12
|
flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12
|
||||||
flutter_tts: 0f492aab6accf87059b72354fcb4ba934304771d
|
flutter_tts: 0f492aab6accf87059b72354fcb4ba934304771d
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>NSContactsUsageDescription</key>
|
||||||
|
<string>This app requires contacts access to function properly.</string>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>12.0</string>
|
||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -37,11 +41,11 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>59</string>
|
<string>67</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>4.3.59</string>
|
<string>4.3.67</string>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string></string>
|
<string></string>
|
||||||
<key>FirebaseAppDelegateProxyEnabled</key>
|
<key>FirebaseAppDelegateProxyEnabled</key>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ class BoxName {
|
|||||||
static const String packagInfo = "packagInfo";
|
static const String packagInfo = "packagInfo";
|
||||||
static const String isVerified = 'isVerified';
|
static const String isVerified = 'isVerified';
|
||||||
static const String isFirstTime = 'isFirstTime';
|
static const String isFirstTime = 'isFirstTime';
|
||||||
|
static const String isSavedPhones = 'isSavedPhones';
|
||||||
static const String statusDriverLocation = "statusDriverLocation";
|
static const String statusDriverLocation = "statusDriverLocation";
|
||||||
static const String isTest = "isTest";
|
static const String isTest = "isTest";
|
||||||
static const String password = "password";
|
static const String password = "password";
|
||||||
|
|||||||
@@ -57,17 +57,21 @@ class AppLink {
|
|||||||
static String deletePassengersPromo = "$promo/delete.php";
|
static String deletePassengersPromo = "$promo/delete.php";
|
||||||
static String updatePassengersPromo = "$promo/update.php";
|
static String updatePassengersPromo = "$promo/update.php";
|
||||||
|
|
||||||
|
//===============contact==========================
|
||||||
|
static String savePhones = "$server/ride/egyptPhones/add.php";
|
||||||
|
static String getPhones = "$server/ride/egyptPhones/get.php";
|
||||||
|
|
||||||
////=======================cancelRide===================
|
////=======================cancelRide===================
|
||||||
static String ride = '$server/ride';
|
static String ride = '$server/ride';
|
||||||
static String addCancelRideFromPassenger = "$server/ride/cancelRide/add.php";
|
static String addCancelRideFromPassenger = "$server/ride/cancelRide/add.php";
|
||||||
static String cancelRide = "$server/ride/cancelRide/get.php";
|
static String cancelRide = "$server/ride/cancelRide/get.php";
|
||||||
//-----------------ridessss------------------
|
//-----------------ridessss------------------
|
||||||
static String addRides = "$ride/rides/add.php";
|
static String addRides = "$ride/rides/add.php";
|
||||||
static String getRides = "$server/ride/rides/get.php";
|
static String getRides = "$endPoint/ride/rides/get.php";
|
||||||
static String getRideOrderID = "$server/ride/rides/getRideOrderID.php";
|
static String getRideOrderID = "$endPoint/ride/rides/getRideOrderID.php";
|
||||||
static String getRideStatus = "$server/ride/rides/getRideStatus.php";
|
static String getRideStatus = "$endPoint/ride/rides/getRideStatus.php";
|
||||||
static String getRideStatusBegin =
|
static String getRideStatusBegin =
|
||||||
"$server/ride/rides/getRideStatusBegin.php";
|
"$endPoint/ride/rides/getRideStatusBegin.php";
|
||||||
static String getRideStatusFromStartApp =
|
static String getRideStatusFromStartApp =
|
||||||
"$ride/rides/getRideStatusFromStartApp.php";
|
"$ride/rides/getRideStatusFromStartApp.php";
|
||||||
static String updateRides = "$server/ride/rides/update.php";
|
static String updateRides = "$server/ride/rides/update.php";
|
||||||
@@ -116,6 +120,17 @@ class AppLink {
|
|||||||
"$ride/notificationCaptain/update.php";
|
"$ride/notificationCaptain/update.php";
|
||||||
static String deleteNotificationCaptain =
|
static String deleteNotificationCaptain =
|
||||||
"$ride/notificationCaptain/delete.php";
|
"$ride/notificationCaptain/delete.php";
|
||||||
|
//-----------------invitor------------------
|
||||||
|
|
||||||
|
static String addInviteDriver = "$server/ride/invitor/add.php";
|
||||||
|
static String addInvitationPassenger =
|
||||||
|
"$server/ride/invitor/addInvitationPassenger.php";
|
||||||
|
static String getInviteDriver = "$server/ride/invitor/get.php";
|
||||||
|
static String getDriverInvitationToPassengers =
|
||||||
|
"$server/ride/invitor/getDriverInvitationToPassengers.php";
|
||||||
|
static String updateInviteDriver = "$server/ride/invitor/update.php";
|
||||||
|
static String updatePassengerGift =
|
||||||
|
"$server/ride/invitor/updatePassengerGift.php";
|
||||||
//-----------------Api Key------------------
|
//-----------------Api Key------------------
|
||||||
static String addApiKey = "$ride/apiKey/add.php";
|
static String addApiKey = "$ride/apiKey/add.php";
|
||||||
static String getApiKey = "$ride/apiKey/get.php";
|
static String getApiKey = "$ride/apiKey/get.php";
|
||||||
@@ -125,6 +140,7 @@ class AppLink {
|
|||||||
|
|
||||||
//-----------------Feed Back------------------
|
//-----------------Feed Back------------------
|
||||||
static String addFeedBack = "$ride/feedBack/add.php";
|
static String addFeedBack = "$ride/feedBack/add.php";
|
||||||
|
static String uploadAudio = "$ride/feedBack/upload_audio.php";
|
||||||
static String getFeedBack = "$ride/feedBack/get.php";
|
static String getFeedBack = "$ride/feedBack/get.php";
|
||||||
static String updateFeedBack = "$ride/feedBack/updateFeedBack.php";
|
static String updateFeedBack = "$ride/feedBack/updateFeedBack.php";
|
||||||
|
|
||||||
|
|||||||
22
lib/constant/notification.dart
Normal file
22
lib/constant/notification.dart
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
List<String> messages = [
|
||||||
|
"🚗 عروض مميزة: استمتع بأقل الأسعار وأفضل العروض! افتح تطبيق سفر الآن لتحصل على المزيد من الخيارات. 🌟",
|
||||||
|
"💸 وفر الآن: وفر مع تطبيق سفر! عروض مستمرة وخيارات متعددة تناسب احتياجاتك. 🔥",
|
||||||
|
"🔒 أمان وراحة: مع تطبيق سفر، احصل على أمان وراحة بأفضل الأسعار! 🚕",
|
||||||
|
"💼 خيارات متنوعة: استفد من خيارات متنوعة وأسعار تنافسية على تطبيق سفر، الأفضل دائماً. 🌐",
|
||||||
|
"💵 توفير مضمون: حافظ على ميزانيتك وسافر بأمان مع تطبيق سفر – العروض لا تتوقف! 🎉",
|
||||||
|
"🌍 وجهات مميزة: أفضل وجهات السفر، بأقل الأسعار مع تطبيق سفر – تابعنا الآن! 🛤️",
|
||||||
|
"🛣️ سهولة وراحة: رحلاتك أصبحت أسهل وأرخص – سافر معنا وتمتع بأفضل التجارب. 🎊",
|
||||||
|
"📲 حجز سهل: احجز رحلتك بسهولة وأمان مع سفر – المزيد من الخصومات في انتظارك! 🎁",
|
||||||
|
"👑 فئة مميزة: خليك من الفئة المميزة واستفد بأفضل الأسعار مع تطبيق سفر. 💯",
|
||||||
|
"💡 خيارات متعددة: نوفر لك خيارات متعددة وسعر مناسب – جرب تطبيق سفر الآن! 🚖",
|
||||||
|
"✨ عروض متجددة: العروض لا تتوقف على تطبيق سفر – احجز رحلتك الآن وتمتع بالمزيد! 📅",
|
||||||
|
"🚀 سهولة الوصول: السفر أصبح أسهل وأسرع مع تطبيق سفر – كن مستعدًا لأفضل التجارب! 🌠",
|
||||||
|
"🧳 راحة وأمان: تطبيق سفر يقدم لك أمان وراحة بأقل الأسعار! 📉",
|
||||||
|
"🔥 عروض فورية: احجز الآن واستمتع بعروض لا تُفوّت على تطبيق سفر! 🚘",
|
||||||
|
"🚖 أسعار تنافسية: اختر رحلتك الآن بأسعار تنافسية وتمتع بالراحة والأمان مع تطبيق سفر. ✅",
|
||||||
|
"💥 أسعار خاصة: أسعار خاصة بانتظارك على تطبيق سفر! افتح التطبيق الآن واحجز رحلتك. 🌐",
|
||||||
|
"🌟 راحة البال: انطلق بأمان وراحة مع تطبيق سفر – استمتع بأفضل الأسعار. 💸",
|
||||||
|
"📍 خصومات حصرية: استفد من الخصومات الحصرية والعروض المستمرة على تطبيق سفر! 🛤️",
|
||||||
|
"🛫 تجربة سهلة: رحلاتك أصبحت أفضل وأسهل مع تطبيق سفر – افتح التطبيق واستمتع بالتجربة. ✨",
|
||||||
|
"🔔 عروض لا مثيل لها: كن جاهزًا لعروض لا مثيل لها! تطبيق سفر يقدم لك أفضل الخيارات بأقل الأسعار. 🎉",
|
||||||
|
];
|
||||||
@@ -43,7 +43,9 @@ class AppStyle {
|
|||||||
static BoxDecoration boxDecoration = const BoxDecoration(
|
static BoxDecoration boxDecoration = const BoxDecoration(
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: AppColor.accentColor, blurRadius: 5, offset: Offset(2, 4)),
|
color: Color.fromARGB(255, 218, 218, 255),
|
||||||
|
blurRadius: 5,
|
||||||
|
offset: Offset(2, 4)),
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: AppColor.accentColor, blurRadius: 5, offset: Offset(-2, -2))
|
color: AppColor.accentColor, blurRadius: 5, offset: Offset(-2, -2))
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:SEFER/constant/info.dart';
|
import 'package:SEFER/constant/info.dart';
|
||||||
import 'package:SEFER/controller/firebase/firbase_messge.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/login_page.dart';
|
||||||
import 'package:SEFER/views/auth/sms_verfy_page.dart';
|
import 'package:SEFER/views/auth/sms_verfy_page.dart';
|
||||||
import 'package:SEFER/views/widgets/my_dialog.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:SEFER/views/home/map_page_passenger.dart';
|
||||||
import 'package:location/location.dart';
|
import 'package:location/location.dart';
|
||||||
|
|
||||||
|
import '../../print.dart';
|
||||||
import '../functions/package_info.dart';
|
import '../functions/package_info.dart';
|
||||||
|
|
||||||
class LoginController extends GetxController {
|
class LoginController extends GetxController {
|
||||||
@@ -90,23 +92,22 @@ class LoginController extends GetxController {
|
|||||||
} else {
|
} else {
|
||||||
var jsonDecoeded = jsonDecode(res);
|
var jsonDecoeded = jsonDecode(res);
|
||||||
if (jsonDecoeded.isNotEmpty) {
|
if (jsonDecoeded.isNotEmpty) {
|
||||||
|
var d = jsonDecoeded['data'][0];
|
||||||
if (jsonDecoeded['status'] == 'success' &&
|
if (jsonDecoeded['status'] == 'success' &&
|
||||||
jsonDecoeded['data'][0]['verified'].toString() == '1') {
|
d['verified'].toString() == '1') {
|
||||||
//
|
//
|
||||||
|
|
||||||
box.write(BoxName.isVerified, '1');
|
box.write(BoxName.isVerified, '1');
|
||||||
box.write(BoxName.email, jsonDecoeded['data'][0]['email']);
|
box.write(BoxName.email, d['email']);
|
||||||
box.write(BoxName.phone, jsonDecoeded['data'][0]['phone']);
|
box.write(BoxName.phone, d['phone']);
|
||||||
box.write(BoxName.isTest, '1');
|
box.write(BoxName.isTest, '1');
|
||||||
box.write(BoxName.package, jsonDecoeded['data'][0]['package']);
|
box.write(BoxName.package, d['package']);
|
||||||
box.write(BoxName.promo, jsonDecoeded['data'][0]['promo']);
|
box.write(BoxName.promo, d['promo']);
|
||||||
box.write(BoxName.discount, jsonDecoeded['data'][0]['discount']);
|
box.write(BoxName.discount, d['discount']);
|
||||||
box.write(BoxName.validity, jsonDecoeded['data'][0]['validity']);
|
box.write(BoxName.validity, d['validity']);
|
||||||
box.write(BoxName.isInstall,
|
box.write(BoxName.isInstall, d['isInstall'] ?? 'none');
|
||||||
jsonDecoeded['data'][0]['isInstall'] ?? 'none');
|
box.write(BoxName.isGiftToken, d['isGiftToken'] ?? 'none');
|
||||||
box.write(BoxName.isGiftToken,
|
box.write(BoxName.inviteCode, d['inviteCode'] ?? 'none');
|
||||||
jsonDecoeded['data'][0]['isGiftToken'] ?? 'none');
|
|
||||||
box.write(BoxName.inviteCode,
|
|
||||||
jsonDecoeded['data'][0]['inviteCode'] ?? 'none');
|
|
||||||
|
|
||||||
var token = await CRUD().get(link: AppLink.getTokens, payload: {
|
var token = await CRUD().get(link: AppLink.getTokens, payload: {
|
||||||
'passengerID': box.read(BoxName.passengerID).toString()
|
'passengerID': box.read(BoxName.passengerID).toString()
|
||||||
@@ -114,11 +115,11 @@ class LoginController extends GetxController {
|
|||||||
if (token != 'failure') {
|
if (token != 'failure') {
|
||||||
if (jsonDecode(token)['data'][0]['token'] !=
|
if (jsonDecode(token)['data'][0]['token'] !=
|
||||||
box.read(BoxName.tokenFCM)) {
|
box.read(BoxName.tokenFCM)) {
|
||||||
Get.put(FirebaseMessagesController())
|
Get.put(FirebaseMessagesController()).sendNotificationToDriverMAP(
|
||||||
.sendNotificationToAnyWithoutData(
|
|
||||||
'token change'.tr,
|
'token change'.tr,
|
||||||
'change device'.tr,
|
'change device'.tr,
|
||||||
jsonDecode(token)['data'][0]['token'].toString(),
|
jsonDecode(token)['data'][0]['token'].toString(),
|
||||||
|
[],
|
||||||
'cancel.wav',
|
'cancel.wav',
|
||||||
);
|
);
|
||||||
Future.delayed(const Duration(seconds: 1));
|
Future.delayed(const Duration(seconds: 1));
|
||||||
@@ -153,10 +154,10 @@ class LoginController extends GetxController {
|
|||||||
Get.offAll(() => const MapPagePassenger());
|
Get.offAll(() => const MapPagePassenger());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
print('same');
|
||||||
}
|
}
|
||||||
} // Logging to check if inviteCode is written correctly
|
} // 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' &&
|
if (box.read(BoxName.inviteCode).toString() != 'none' &&
|
||||||
box.read(BoxName.isInstall).toString() != '1') {
|
box.read(BoxName.isInstall).toString() != '1') {
|
||||||
@@ -171,15 +172,22 @@ class LoginController extends GetxController {
|
|||||||
middleText: "Your invite code was successfully applied!"
|
middleText: "Your invite code was successfully applied!"
|
||||||
.tr, // Automatically translates based on the current locale
|
.tr, // Automatically translates based on the current locale
|
||||||
onConfirm: () {
|
onConfirm: () {
|
||||||
CRUD().post(link: AppLink.addPassengersPromo, payload: {
|
try {
|
||||||
"promoCode":
|
CRUD().post(link: AppLink.addPassengersPromo, payload: {
|
||||||
'S-${box.read(BoxName.name).toString().split(' ')[0]}',
|
"promoCode":
|
||||||
"amount": '25',
|
'S-${box.read(BoxName.name).toString().split(' ')[0]}',
|
||||||
"passengerID": box.read(BoxName.passengerID).toString(),
|
"amount": '25',
|
||||||
"description": 'promo first'
|
"passengerID": box.read(BoxName.passengerID).toString(),
|
||||||
});
|
"description": 'promo first'
|
||||||
Get.offAll(() =>
|
});
|
||||||
const MapPagePassenger()); // Navigate to MapPagePassenger after confirmation
|
} 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
|
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 {
|
void login() async {
|
||||||
isloading = true;
|
isloading = true;
|
||||||
update();
|
update();
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'dart:math';
|
|||||||
|
|
||||||
import 'package:SEFER/constant/colors.dart';
|
import 'package:SEFER/constant/colors.dart';
|
||||||
import 'package:SEFER/controller/auth/login_controller.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/controller/local/phone_intel/phone_number.dart';
|
||||||
import 'package:SEFER/views/home/map_page_passenger.dart';
|
import 'package:SEFER/views/home/map_page_passenger.dart';
|
||||||
import 'package:SEFER/views/widgets/my_dialog.dart';
|
import 'package:SEFER/views/widgets/my_dialog.dart';
|
||||||
@@ -134,66 +135,51 @@ class RegisterController extends GetxController {
|
|||||||
String phoneNumber = phoneController.text;
|
String phoneNumber = phoneController.text;
|
||||||
|
|
||||||
// Check if the phone number is from Egypt (Assuming Egyptian numbers start with +20)
|
// 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') {
|
if (phoneController.text.isNotEmpty) {
|
||||||
var data = jsonDecode(responseChecker);
|
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 (responseChecker != 'failure') {
|
||||||
if (data['message'][0]['verified'].toString() == '1') {
|
var data = jsonDecode(responseChecker);
|
||||||
Get.snackbar('Phone number is verified before'.tr, '',
|
|
||||||
backgroundColor: AppColor.greenColor);
|
// If the phone number is already verified
|
||||||
box.write(BoxName.isVerified, '1');
|
if (data['message'][0]['verified'].toString() == '1') {
|
||||||
box.write(BoxName.phone, phoneNumber);
|
Get.snackbar('Phone number is verified before'.tr, '',
|
||||||
Get.offAll(const MapPagePassenger());
|
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 {
|
} else {
|
||||||
// If the phone number is not verified, send OTP
|
|
||||||
// if (isEgyptianNumber) {
|
|
||||||
// if (isValidEgyptianPhoneNumber(
|
|
||||||
// phoneNumber.toString().split('+2')[1])) {
|
|
||||||
await sendOtp(phoneNumber, randomNumber, isEgyptianNumber,
|
await sendOtp(phoneNumber, randomNumber, isEgyptianNumber,
|
||||||
smsEgyptController);
|
smsEgyptController);
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If verification check fails, still send OTP
|
sendOtp(
|
||||||
// if (isEgyptianNumber) {
|
|
||||||
// if (isValidEgyptianPhoneNumber(
|
|
||||||
// phoneNumber.toString().split('+2')[1])) {
|
|
||||||
await sendOtp(
|
|
||||||
phoneNumber, randomNumber, isEgyptianNumber, smsEgyptController);
|
phoneNumber, randomNumber, isEgyptianNumber, smsEgyptController);
|
||||||
// } else {
|
|
||||||
// MyDialog().getDialog(
|
|
||||||
// 'Error'.tr, "Phone number isn't an Egyptian phone number".tr,
|
|
||||||
// () {
|
|
||||||
// Get.back();
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// MyDialog().getDialog(
|
MyDialog().getDialog(
|
||||||
// 'Error'.tr, 'Phone number must be exactly 11 digits long'.tr, () {
|
'Error'.tr, 'Phone number must be exactly 11 digits long'.tr, () {
|
||||||
// Get.back();
|
Get.back();
|
||||||
// });
|
});
|
||||||
sendOtp(
|
// sendOtp(
|
||||||
phoneNumber, randomNumber, isEgyptianNumber, smsEgyptController);
|
// phoneNumber, randomNumber, isEgyptianNumber, smsEgyptController);
|
||||||
print(phoneNumber);
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Handle error
|
// Handle error
|
||||||
print('Error: $e');
|
|
||||||
} finally {
|
} finally {
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
update();
|
update();
|
||||||
@@ -205,34 +191,14 @@ class RegisterController extends GetxController {
|
|||||||
SmsEgyptController controller) async {
|
SmsEgyptController controller) async {
|
||||||
// Trim any leading or trailing whitespace from the phone number
|
// Trim any leading or trailing whitespace from the phone number
|
||||||
phoneNumber = phoneNumber.trim();
|
phoneNumber = phoneNumber.trim();
|
||||||
Log.print('phoneNumber: ${phoneNumber}');
|
await CRUD().post(link: AppLink.sendVerifyOtpMessage, payload: {
|
||||||
|
'phone_number': phoneNumber,
|
||||||
|
'token': otp.toString(),
|
||||||
|
});
|
||||||
if (isEgyptian) {
|
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());
|
await controller.sendSmsEgypt(phoneNumber, otp.toString());
|
||||||
print('SMS sent to Egyptian phone number: $phoneNumber');
|
|
||||||
} else {
|
} 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());
|
await CRUD().sendWhatsAppAuth(phoneNumber, otp.toString());
|
||||||
print('WhatsApp message sent to non-Egyptian phone number: $phoneNumber');
|
|
||||||
}
|
}
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
|
|
||||||
@@ -243,98 +209,72 @@ class RegisterController extends GetxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
verifySMSCode() async {
|
verifySMSCode() async {
|
||||||
// if (formKey3.currentState!.validate()) {
|
try {
|
||||||
Log.print('phoneController.text: ${phoneController.text}');
|
if (formKey3.currentState!.validate()) {
|
||||||
// if (isValidEgyptianPhoneNumber(phoneController.text)) {
|
var res = await CRUD().post(link: AppLink.verifyOtpMessage, payload: {
|
||||||
var res = await CRUD().post(link: AppLink.verifyOtpMessage, payload: {
|
'phone_number': phoneController.text,
|
||||||
'phone_number': phoneController.text,
|
'token': verifyCode.text.toString(),
|
||||||
'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],
|
|
||||||
};
|
|
||||||
|
|
||||||
var res1 = await CRUD().post(
|
if (res != 'failure') {
|
||||||
link: AppLink.signUp,
|
box.write(BoxName.phoneDriver, phoneController.text);
|
||||||
payload: payload,
|
var nameParts = box.read(BoxName.name).toString().split(' ');
|
||||||
);
|
var firstName = nameParts.isNotEmpty ? nameParts[0] : 'unknown';
|
||||||
if (res1 != 'failure') {
|
var lastName = nameParts.length > 1 ? nameParts[1] : 'unknown';
|
||||||
CRUD().post(
|
|
||||||
link: '${AppLink.seferAlexandriaServer}/auth/signup.php',
|
var payload = {
|
||||||
payload: payload,
|
'id': box.read(BoxName.passengerID),
|
||||||
);
|
'phone': phoneController.text,
|
||||||
CRUD().post(
|
'email': box.read(BoxName.email),
|
||||||
link: '${AppLink.seferGizaServer}/auth/signup.php',
|
'password': 'unknown',
|
||||||
payload: payload,
|
'gender': 'unknown',
|
||||||
);
|
'birthdate': '2002-01-01',
|
||||||
box.write(BoxName.isVerified, '1');
|
'site': box.read(BoxName.passengerPhotoUrl) ?? 'unknown',
|
||||||
box.write(BoxName.isFirstTime, '0');
|
'first_name': firstName,
|
||||||
box.write(BoxName.phone, phoneController.text);
|
'last_name': lastName,
|
||||||
// Get.offAll(const MapPagePassenger());
|
};
|
||||||
Get.put(LoginController()).loginUsingCredentials(
|
|
||||||
box.read(BoxName.passengerID).toString(),
|
var res1 = await CRUD().post(
|
||||||
box.read(BoxName.email).toString(),
|
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 {
|
} catch (e) {
|
||||||
Get.snackbar(
|
addError(e.toString(), 'passenger sign up ');
|
||||||
'Error'.tr, "The email or phone number is already registered.".tr,
|
Get.snackbar('Error'.tr, "Something went wrong. Please try again.".tr,
|
||||||
backgroundColor: Colors.redAccent);
|
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 {
|
sendVerifications() async {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'package:SEFER/views/widgets/my_dialog.dart';
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -65,6 +66,9 @@ class FirebaseMessagesController extends GetxController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NotificationController notificationController =
|
||||||
|
Get.find<NotificationController>();
|
||||||
|
|
||||||
Future getTokens() async {
|
Future getTokens() async {
|
||||||
String? basicAuthCredentials =
|
String? basicAuthCredentials =
|
||||||
await storage.read(key: BoxName.basicAuthCredentials);
|
await storage.read(key: BoxName.basicAuthCredentials);
|
||||||
@@ -118,6 +122,10 @@ class FirebaseMessagesController extends GetxController {
|
|||||||
|
|
||||||
void fireBaseTitles(RemoteMessage message) {
|
void fireBaseTitles(RemoteMessage message) {
|
||||||
if (message.notification!.title! == 'Order'.tr) {
|
if (message.notification!.title! == 'Order'.tr) {
|
||||||
|
if (Platform.isAndroid) {
|
||||||
|
notificationController.showNotification(
|
||||||
|
'Order', message.notification!.body!, 'Order');
|
||||||
|
}
|
||||||
} else if (message.notification!.title! == 'Apply Ride'.tr) {
|
} else if (message.notification!.title! == 'Apply Ride'.tr) {
|
||||||
var passengerList = message.data['passengerList'];
|
var passengerList = message.data['passengerList'];
|
||||||
|
|
||||||
@@ -128,20 +136,22 @@ class FirebaseMessagesController extends GetxController {
|
|||||||
Get.find<MapPassengerController>().isSearchingWindow == false;
|
Get.find<MapPassengerController>().isSearchingWindow == false;
|
||||||
Get.find<MapPassengerController>().update();
|
Get.find<MapPassengerController>().update();
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
NotificationController().showNotification(
|
notificationController.showNotification(
|
||||||
'Apply Order'.tr, 'Driver Applied the Ride for You'.tr, 'order1');
|
'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();
|
// driverAppliedTripSnakBar();
|
||||||
} else if (message.notification!.title! == 'Promo'.tr) {
|
} else if (message.notification!.title! == 'Promo'.tr) {
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
NotificationController()
|
notificationController.showNotification(
|
||||||
.showNotification('Promo', 'Show latest promo'.tr, 'promo');
|
'Promo', 'Show latest promo'.tr, 'promo');
|
||||||
}
|
}
|
||||||
Get.to(const PromosPassengerPage());
|
Get.to(const PromosPassengerPage());
|
||||||
} else if (message.notification!.title! == 'Trip Monitoring'.tr) {
|
} else if (message.notification!.title! == 'Trip Monitoring'.tr) {
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
NotificationController()
|
notificationController.showNotification(
|
||||||
.showNotification('Trip Monitoring'.tr, '', 'iphone_ringtone');
|
'Trip Monitoring'.tr, '', 'iphone_ringtone');
|
||||||
}
|
}
|
||||||
var myListString = message.data['passengerList'];
|
var myListString = message.data['passengerList'];
|
||||||
var myList = jsonDecode(myListString) as List<dynamic>;
|
var myList = jsonDecode(myListString) as List<dynamic>;
|
||||||
@@ -151,65 +161,67 @@ class FirebaseMessagesController extends GetxController {
|
|||||||
});
|
});
|
||||||
} else if (message.notification!.title! == 'token change'.tr) {
|
} else if (message.notification!.title! == 'token change'.tr) {
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
NotificationController()
|
notificationController.showNotification(
|
||||||
.showNotification('token change'.tr, 'token change'.tr, 'cancel');
|
'token change'.tr, 'token change'.tr, 'cancel');
|
||||||
}
|
}
|
||||||
GoogleSignInHelper.signOut();
|
GoogleSignInHelper.signOut();
|
||||||
} else if (message.notification!.title! == 'DriverIsGoingToPassenger'.tr) {
|
} else if (message.notification!.title! == 'DriverIsGoingToPassenger'.tr) {
|
||||||
Get.find<MapPassengerController>().isDriverInPassengerWay = true;
|
Get.find<MapPassengerController>().isDriverInPassengerWay = true;
|
||||||
Get.find<MapPassengerController>().update();
|
Get.find<MapPassengerController>().update();
|
||||||
if (Platform.isAndroid) {
|
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');
|
'Please stay on the picked point.'.tr, 'tone1');
|
||||||
}
|
}
|
||||||
// Get.snackbar('Driver is Going To Passenger', '',
|
// Get.snackbar('Driver is Going To Passenger', '',
|
||||||
// backgroundColor: AppColor.greenColor);
|
// backgroundColor: AppColor.greenColor);
|
||||||
} else if (message.notification!.title! == 'message From passenger') {
|
} else if (message.notification!.title! == 'message From passenger') {
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
NotificationController()
|
notificationController.showNotification(
|
||||||
.showNotification('message From passenger'.tr, ''.tr, 'tone2');
|
'message From passenger'.tr, ''.tr, 'tone2');
|
||||||
}
|
}
|
||||||
passengerDialog(message.notification!.body!);
|
passengerDialog(message.notification!.body!);
|
||||||
|
|
||||||
update();
|
update();
|
||||||
} else if (message.notification!.title! == 'message From Driver') {
|
} else if (message.notification!.title! == 'message From Driver') {
|
||||||
passengerDialog(message.notification!.body!);
|
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
NotificationController()
|
notificationController.showNotification(
|
||||||
.showNotification('message From passenger'.tr, ''.tr, 'tone2');
|
'message From passenger'.tr, ''.tr, 'tone2');
|
||||||
}
|
}
|
||||||
|
passengerDialog(message.notification!.body!);
|
||||||
|
|
||||||
update();
|
update();
|
||||||
} else if (message.notification!.title! == 'RideIsBegin'.tr) {
|
} else if (message.notification!.title! == 'RideIsBegin'.tr) {
|
||||||
|
if (Platform.isAndroid) {
|
||||||
|
notificationController.showNotification(
|
||||||
|
'Trip is Begin'.tr, ''.tr, 'start');
|
||||||
|
}
|
||||||
Get.find<MapPassengerController>().getBeginRideFromDriver();
|
Get.find<MapPassengerController>().getBeginRideFromDriver();
|
||||||
// Get.snackbar('RideIsBegin', '', backgroundColor: AppColor.greenColor);
|
// Get.snackbar('RideIsBegin', '', backgroundColor: AppColor.greenColor);
|
||||||
box.write(BoxName.passengerWalletTotal, '0');
|
box.write(BoxName.passengerWalletTotal, '0');
|
||||||
update();
|
update();
|
||||||
if (Platform.isAndroid) {
|
|
||||||
NotificationController()
|
|
||||||
.showNotification('Trip is Begin'.tr, ''.tr, 'start');
|
|
||||||
}
|
|
||||||
} else if (message.notification!.title! == 'Hi ,I will go now'.tr) {
|
} else if (message.notification!.title! == 'Hi ,I will go now'.tr) {
|
||||||
// Get.snackbar('Hi ,I will go now', '',
|
// Get.snackbar('Hi ,I will go now', '',
|
||||||
// backgroundColor: AppColor.greenColor);
|
// backgroundColor: AppColor.greenColor);
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
NotificationController().showNotification(
|
notificationController.showNotification(
|
||||||
'Passenger come to you'.tr, 'Hi ,I will go now'.tr, 'tone2');
|
'Passenger come to you'.tr, 'Hi ,I will go now'.tr, 'tone2');
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
} else if (message.notification!.title! == 'Hi ,I Arrive your site'.tr) {
|
} else if (message.notification!.title! == 'Hi ,I Arrive your site'.tr) {
|
||||||
driverArrivePassengerDialoge();
|
driverArrivePassengerDialoge();
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
NotificationController()
|
notificationController.showNotification(
|
||||||
.showNotification('Hi ,I Arrive your site'.tr, ''.tr, 'tone2');
|
'Hi ,I Arrive your site'.tr, ''.tr, 'tone2');
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
} else if (message.notification!.title! == "Cancel Trip from driver".tr) {
|
} else if (message.notification!.title! == "Cancel Trip from driver".tr) {
|
||||||
Get.back();
|
Get.back();
|
||||||
|
|
||||||
Get.defaultDialog(
|
Get.defaultDialog(
|
||||||
title: "The driver canceled your ride.".tr,
|
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(
|
confirm: MyElevatedButton(
|
||||||
|
kolor: AppColor.greenColor,
|
||||||
title: 'Ok'.tr,
|
title: 'Ok'.tr,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
Get.back();
|
Get.back();
|
||||||
@@ -219,6 +231,7 @@ class FirebaseMessagesController extends GetxController {
|
|||||||
),
|
),
|
||||||
cancel: MyElevatedButton(
|
cancel: MyElevatedButton(
|
||||||
title: 'Cancel'.tr,
|
title: 'Cancel'.tr,
|
||||||
|
kolor: AppColor.redColor,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.offAll(const MapPagePassenger());
|
Get.offAll(const MapPagePassenger());
|
||||||
},
|
},
|
||||||
@@ -230,7 +243,7 @@ class FirebaseMessagesController extends GetxController {
|
|||||||
var myListString = message.data['passengerList'];
|
var myListString = message.data['passengerList'];
|
||||||
var driverList = jsonDecode(myListString) as List<dynamic>;
|
var driverList = jsonDecode(myListString) as List<dynamic>;
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
NotificationController().showNotification(
|
notificationController.showNotification(
|
||||||
'Driver Finish Trip'.tr,
|
'Driver Finish Trip'.tr,
|
||||||
'you will pay to Driver'.tr + ' ${driverList[3].toString()} \$'.tr,
|
'you will pay to Driver'.tr + ' ${driverList[3].toString()} \$'.tr,
|
||||||
'tone1');
|
'tone1');
|
||||||
@@ -267,7 +280,7 @@ class FirebaseMessagesController extends GetxController {
|
|||||||
var driverList = jsonDecode(myListString) as List<dynamic>;
|
var driverList = jsonDecode(myListString) as List<dynamic>;
|
||||||
// if (Platform.isAndroid) {
|
// if (Platform.isAndroid) {
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
NotificationController().showNotification(
|
notificationController.showNotification(
|
||||||
'Call Income'.tr,
|
'Call Income'.tr,
|
||||||
message.notification!.body!,
|
message.notification!.body!,
|
||||||
'iphone_ringtone',
|
'iphone_ringtone',
|
||||||
@@ -287,7 +300,7 @@ class FirebaseMessagesController extends GetxController {
|
|||||||
var driverList = jsonDecode(myListString) as List<dynamic>;
|
var driverList = jsonDecode(myListString) as List<dynamic>;
|
||||||
// if (Platform.isAndroid) {
|
// if (Platform.isAndroid) {
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
NotificationController().showNotification(
|
notificationController.showNotification(
|
||||||
'Call Income'.tr,
|
'Call Income'.tr,
|
||||||
message.notification!.body!,
|
message.notification!.body!,
|
||||||
'iphone_ringtone',
|
'iphone_ringtone',
|
||||||
@@ -305,7 +318,7 @@ class FirebaseMessagesController extends GetxController {
|
|||||||
var myListString = message.data['passengerList'];
|
var myListString = message.data['passengerList'];
|
||||||
var driverList = jsonDecode(myListString) as List<dynamic>;
|
var driverList = jsonDecode(myListString) as List<dynamic>;
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
NotificationController().showNotification(
|
notificationController.showNotification(
|
||||||
'Call End'.tr,
|
'Call End'.tr,
|
||||||
message.notification!.body!,
|
message.notification!.body!,
|
||||||
'tone2',
|
'tone2',
|
||||||
@@ -321,7 +334,7 @@ class FirebaseMessagesController extends GetxController {
|
|||||||
// 'message',
|
// 'message',
|
||||||
// backgroundColor: AppColor.redColor);
|
// backgroundColor: AppColor.redColor);
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
NotificationController().showNotification(
|
notificationController.showNotification(
|
||||||
'Driver Cancel Your Trip'.tr,
|
'Driver Cancel Your Trip'.tr,
|
||||||
'you will pay to Driver you will be pay the cost of driver time look to your SEFER Wallet'
|
'you will pay to Driver you will be pay the cost of driver time look to your SEFER Wallet'
|
||||||
.tr,
|
.tr,
|
||||||
@@ -346,7 +359,7 @@ class FirebaseMessagesController extends GetxController {
|
|||||||
|
|
||||||
else if (message.notification!.title! == 'Order Applied'.tr) {
|
else if (message.notification!.title! == 'Order Applied'.tr) {
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
NotificationController().showNotification(
|
notificationController.showNotification(
|
||||||
'The order Accepted by another Driver'.tr,
|
'The order Accepted by another Driver'.tr,
|
||||||
'We regret to inform you that another driver has accepted this order.'
|
'We regret to inform you that another driver has accepted this order.'
|
||||||
.tr,
|
.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(
|
Future<void> sendNotificationToDriverMAP(
|
||||||
String title, String body, String token, List<String> data, String tone,
|
String title, String body, String token, List<String> data, String tone,
|
||||||
{int retryCount = 2}) async {
|
{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 {
|
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:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
import 'package:get/get.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 {
|
class NotificationController extends GetxController {
|
||||||
final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
|
final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
|
||||||
FlutterLocalNotificationsPlugin();
|
FlutterLocalNotificationsPlugin();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onInit() {
|
||||||
|
super.onInit();
|
||||||
|
initNotifications();
|
||||||
|
}
|
||||||
|
|
||||||
// Initializes the local notifications plugin
|
// Initializes the local notifications plugin
|
||||||
Future<void> initNotifications() async {
|
Future<void> initNotifications() async {
|
||||||
const AndroidInitializationSettings android =
|
const AndroidInitializationSettings android =
|
||||||
AndroidInitializationSettings('@mipmap/launcher_icon');
|
AndroidInitializationSettings('@mipmap/launcher_icon');
|
||||||
const InitializationSettings initializationSettings =
|
DarwinInitializationSettings ios = DarwinInitializationSettings(
|
||||||
InitializationSettings(android: android);
|
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);
|
await _flutterLocalNotificationsPlugin.initialize(initializationSettings);
|
||||||
|
|
||||||
|
tz.initializeTimeZones();
|
||||||
|
print('Notifications initialized');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Displays a notification with the given title and message
|
// Displays a notification with the given title and message
|
||||||
void showNotification(String title, String message, String tone) async {
|
void showNotification(String title, String message, String tone) async {
|
||||||
AndroidNotificationDetails android = AndroidNotificationDetails(
|
final AndroidNotificationDetails android = AndroidNotificationDetails(
|
||||||
'high_importance_channel', 'High Importance Notifications',
|
'high_importance_channel',
|
||||||
importance: Importance.max,
|
'High Importance Notifications',
|
||||||
priority: Priority.high,
|
importance: Importance.max,
|
||||||
showWhen: false,
|
priority: Priority.high,
|
||||||
sound: RawResourceAndroidNotificationSound(tone));
|
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);
|
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:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:ui';
|
||||||
import 'package:SEFER/constant/box_name.dart';
|
import 'package:SEFER/constant/box_name.dart';
|
||||||
import 'package:SEFER/constant/links.dart';
|
import 'package:SEFER/constant/links.dart';
|
||||||
import 'package:SEFER/main.dart';
|
import 'package:SEFER/main.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:SEFER/env/env.dart';
|
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/api_key.dart';
|
||||||
|
|
||||||
|
import '../../constant/colors.dart';
|
||||||
import '../../print.dart';
|
import '../../print.dart';
|
||||||
import '../../views/widgets/elevated_btn.dart';
|
import '../../views/widgets/elevated_btn.dart';
|
||||||
|
import 'add_error.dart';
|
||||||
import 'upload_image.dart';
|
import 'upload_image.dart';
|
||||||
|
|
||||||
class CRUD {
|
class CRUD {
|
||||||
@@ -29,8 +35,9 @@ class CRUD {
|
|||||||
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}',
|
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
Log.print('payload: ${payload}');
|
|
||||||
Log.print('response.request: ${response.request}');
|
Log.print('response.request: ${response.request}');
|
||||||
|
Log.print('payload: ${payload}');
|
||||||
Log.print('response.reasonPhrase: ${response.reasonPhrase}');
|
Log.print('response.reasonPhrase: ${response.reasonPhrase}');
|
||||||
|
|
||||||
Log.print('response.body: ${response.body}');
|
Log.print('response.body: ${response.body}');
|
||||||
@@ -44,7 +51,6 @@ class CRUD {
|
|||||||
return jsonData['status'];
|
return jsonData['status'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// }
|
|
||||||
Future<dynamic> getTokenParent({
|
Future<dynamic> getTokenParent({
|
||||||
required String link,
|
required String link,
|
||||||
Map<String, dynamic>? payload,
|
Map<String, dynamic>? payload,
|
||||||
@@ -264,36 +270,83 @@ class CRUD {
|
|||||||
} else {}
|
} 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({
|
Future<dynamic> post({
|
||||||
required String link,
|
required String link,
|
||||||
Map<String, dynamic>? payload,
|
Map<String, dynamic>? payload,
|
||||||
}) async {
|
}) async {
|
||||||
// String? basicAuthCredentials =
|
var url = Uri.parse(link);
|
||||||
// await storage.read(key: BoxName.basicAuthCredentials);
|
try {
|
||||||
var url = Uri.parse(
|
var response = await http.post(
|
||||||
link,
|
url,
|
||||||
);
|
body: payload,
|
||||||
var response = await http.post(
|
headers: {
|
||||||
url,
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
body: payload,
|
'Authorization':
|
||||||
headers: {
|
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
|
||||||
"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('payload: ${payload}');
|
// Log.print('Response.statusCode: ${response.statusCode}');
|
||||||
Log.print('response.request: ${response.request}');
|
Log.print('Response.body: ${response.body}');
|
||||||
Log.print('response.body: ${response.body}');
|
|
||||||
var jsonData = jsonDecode(response.body);
|
if (response.statusCode == 200) {
|
||||||
if (response.statusCode == 200) {
|
try {
|
||||||
if (jsonData['status'] == 'success') {
|
var jsonData = jsonDecode(response.body);
|
||||||
return 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 {
|
} 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 {
|
} catch (e) {
|
||||||
return response.statusCode;
|
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 {
|
Future<dynamic> sendSmsEgypt(String phone, otp) async {
|
||||||
String sender = await getSender();
|
String sender = await getSender();
|
||||||
var body = jsonEncode({
|
var body = jsonEncode({
|
||||||
"username": AppInformation.appName,
|
"username": 'Sefer',
|
||||||
"password": AK.smsPasswordEgypt,
|
"password": AK.smsPasswordEgypt,
|
||||||
"message": "${AppInformation.appName} app code is $otp\ncopy it to app",
|
"message": "${AppInformation.appName} app code is $otp\ncopy it to app",
|
||||||
"language": box.read(BoxName.lang) == 'en' ? "e" : 'r',
|
"language": box.read(BoxName.lang) == 'en' ? "e" : 'r',
|
||||||
|
|||||||
@@ -1,49 +1,50 @@
|
|||||||
import 'package:SEFER/constant/box_name.dart';
|
import 'package:SEFER/constant/box_name.dart';
|
||||||
import 'package:SEFER/main.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_tts/flutter_tts.dart';
|
import 'package:flutter_tts/flutter_tts.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
import '../../main.dart';
|
||||||
|
|
||||||
class TextToSpeechController extends GetxController {
|
class TextToSpeechController extends GetxController {
|
||||||
final flutterTts = FlutterTts();
|
final flutterTts = FlutterTts();
|
||||||
|
|
||||||
// Initialize TTS in initState
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
initTts();
|
initTts();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dispose of TTS when controller is closed
|
|
||||||
@override
|
@override
|
||||||
void onClose() {
|
void onClose() {
|
||||||
|
flutterTts.stop(); // Stop any ongoing TTS
|
||||||
super.onClose();
|
super.onClose();
|
||||||
flutterTts.completionHandler;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to initialize TTS engine
|
// Initialize TTS engine with language check
|
||||||
Future<void> initTts() async {
|
Future<void> initTts() async {
|
||||||
String? lang =
|
try {
|
||||||
WidgetsBinding.instance.platformDispatcher.locale.countryCode;
|
String langCode = box.read(BoxName.lang) ?? 'en-US';
|
||||||
await flutterTts
|
bool isAvailable = await flutterTts.isLanguageAvailable(langCode);
|
||||||
.setLanguage(box.read(BoxName.lang).toString()); //'en-US' Set language
|
|
||||||
// await flutterTts.setLanguage('ar-SA'); //'en-US' Set language
|
// If language is unavailable, default to 'en-US'
|
||||||
// await flutterTts.setLanguage(lang!); //'en-US' Set language
|
if (!isAvailable) {
|
||||||
await flutterTts.setSpeechRate(0.5); // Adjust speech rate
|
langCode = 'en-US';
|
||||||
await flutterTts.setVolume(1.0); // Set volume
|
}
|
||||||
|
|
||||||
|
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
|
// Function to speak the given text
|
||||||
Future<void> speakText(String text) async {
|
Future<void> speakText(String text) async {
|
||||||
try {
|
try {
|
||||||
await flutterTts.awaitSpeakCompletion(true);
|
await flutterTts.awaitSpeakCompletion(true);
|
||||||
var result = await flutterTts.speak(text);
|
await flutterTts.speak(text);
|
||||||
if (result == 1) {
|
|
||||||
// TTS operation has started
|
|
||||||
// You can perform additional operations here, if needed
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Handle error gracefully, e.g., show a message
|
|
||||||
Get.snackbar('Error', 'Failed to speak text: $error');
|
Get.snackbar('Error', 'Failed to speak text: $error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -769,7 +769,8 @@ class MapPassengerController extends GetxController {
|
|||||||
if (res != 'failure') {
|
if (res != 'failure') {
|
||||||
var decode = jsonDecode(res);
|
var decode = jsonDecode(res);
|
||||||
|
|
||||||
if (decode['data']['status'] != 'Apply') {
|
// if (decode['data']['status'] != 'Apply') {
|
||||||
|
if (decode['data']['status'] == 'Begin') {
|
||||||
timeToPassengerFromDriverAfterApplied = 0;
|
timeToPassengerFromDriverAfterApplied = 0;
|
||||||
remainingTime = 0;
|
remainingTime = 0;
|
||||||
remainingTimeToPassengerFromDriverAfterApplied = 0;
|
remainingTimeToPassengerFromDriverAfterApplied = 0;
|
||||||
@@ -1077,7 +1078,7 @@ class MapPassengerController extends GetxController {
|
|||||||
// licensePlate = nearestDriverData['car_plate'].toString();
|
// licensePlate = nearestDriverData['car_plate'].toString();
|
||||||
// startCarLocationSearch(box.read(BoxName.carType));
|
// startCarLocationSearch(box.read(BoxName.carType));
|
||||||
await getCarsLocationByPassengerAndReloadMarker(
|
await getCarsLocationByPassengerAndReloadMarker(
|
||||||
box.read(BoxName.carType), 4500);
|
box.read(BoxName.carType), 3000);
|
||||||
// await getCarsLocationByPassengerAndReloadMarker(
|
// await getCarsLocationByPassengerAndReloadMarker(
|
||||||
// box.read(BoxName.carType), 7000);
|
// box.read(BoxName.carType), 7000);
|
||||||
// await getNearestDriverByPassengerLocation();
|
// await getNearestDriverByPassengerLocation();
|
||||||
@@ -1112,26 +1113,28 @@ class MapPassengerController extends GetxController {
|
|||||||
isDriversTokensSend = false;
|
isDriversTokensSend = false;
|
||||||
|
|
||||||
update();
|
update();
|
||||||
await CRUD()
|
await CRUD().post(
|
||||||
.post(link: "${AppLink.endPoint}/ride/rides/add.php", payload: {
|
link: "${AppLink.seferCairoServer}/ride/rides/add.php",
|
||||||
"start_location": //'${data[0]['start_address']}',
|
payload: {
|
||||||
'${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
|
"start_location": //'${data[0]['start_address']}',
|
||||||
"end_location": //'${data[0]['end_address']}',
|
'${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
|
||||||
'${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
|
"end_location": //'${data[0]['end_address']}',
|
||||||
"date": DateTime.now().toString(),
|
'${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
|
||||||
"time": DateTime.now().toString(),
|
"date": DateTime.now().toString(),
|
||||||
"endtime": durationToAdd.toString(),
|
"time": DateTime.now().toString(),
|
||||||
"price": totalPassenger.toStringAsFixed(2),
|
"endtime": durationToAdd.toString(),
|
||||||
"passenger_id": box.read(BoxName.passengerID).toString(),
|
"price": totalPassenger.toStringAsFixed(2),
|
||||||
"driver_id": dataCarsLocationByPassenger['data'][carsOrder]['driver_id']
|
"passenger_id": box.read(BoxName.passengerID).toString(),
|
||||||
.toString(),
|
"driver_id": dataCarsLocationByPassenger['data'][carsOrder]
|
||||||
"status": "waiting",
|
['driver_id']
|
||||||
'carType': box.read(BoxName.carType),
|
.toString(),
|
||||||
"price_for_driver": totalPassenger.toString(),
|
"status": "waiting",
|
||||||
"price_for_passenger": totalME.toString(),
|
'carType': box.read(BoxName.carType),
|
||||||
"distance": distance.toString(),
|
"price_for_driver": totalPassenger.toString(),
|
||||||
"paymentMethod": paymentController.isWalletChecked.toString(),
|
"price_for_passenger": totalME.toString(),
|
||||||
}).then((value) {
|
"distance": distance.toString(),
|
||||||
|
"paymentMethod": paymentController.isWalletChecked.toString(),
|
||||||
|
}).then((value) {
|
||||||
// List<String> body = [
|
// List<String> body = [
|
||||||
rideId = jsonDecode(value)['message'];
|
rideId = jsonDecode(value)['message'];
|
||||||
List<String> body = [
|
List<String> body = [
|
||||||
@@ -1188,6 +1191,29 @@ class MapPassengerController extends GetxController {
|
|||||||
Log.print(
|
Log.print(
|
||||||
'dataCarsLocationByPassenger[data]: ${dataCarsLocationByPassenger['data'][carsOrder]['token']}');
|
'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));
|
delayAndFetchRideStatus(rideId, box.read(BoxName.carType));
|
||||||
if (shouldFetch == false) {
|
if (shouldFetch == false) {
|
||||||
startTimer();
|
startTimer();
|
||||||
@@ -1211,10 +1237,11 @@ class MapPassengerController extends GetxController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String driverOrderStatus = 'yet';
|
||||||
bool isDriversTokensSend = false;
|
bool isDriversTokensSend = false;
|
||||||
confirmRideForAllDriverAvailable() async {
|
confirmRideForAllDriverAvailable0() async {
|
||||||
await getCarsLocationByPassengerAndReloadMarker(
|
await getCarsLocationByPassengerAndReloadMarker(
|
||||||
box.read(BoxName.carType), 4500);
|
box.read(BoxName.carType), 3500);
|
||||||
if (dataCarsLocationByPassenger != 'failure') {
|
if (dataCarsLocationByPassenger != 'failure') {
|
||||||
// driversToken.remove(driverToken);
|
// driversToken.remove(driverToken);
|
||||||
PaymentController paymentController = Get.find<PaymentController>();
|
PaymentController paymentController = Get.find<PaymentController>();
|
||||||
@@ -1291,33 +1318,38 @@ class MapPassengerController extends GetxController {
|
|||||||
// Log.print('body: ${body}');
|
// Log.print('body: ${body}');
|
||||||
|
|
||||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||||
'OrderSpeed',
|
'OrderSpeed',
|
||||||
rideId.toString(),
|
rideId.toString(),
|
||||||
dataCarsLocationByPassenger['data'][i]['token'].toString(),
|
dataCarsLocationByPassenger['data'][i]['token'].toString(),
|
||||||
body,
|
body,
|
||||||
'order.wav');
|
'order.wav',
|
||||||
|
);
|
||||||
|
driverOrderStatus = 'recive';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
(rideId); //
|
(rideId); //
|
||||||
CRUD().post(link: '${AppLink.endPoint}/ride/rides/add.php', payload: {
|
if (AppLink.endPoint != AppLink.seferCairoServer) {
|
||||||
"start_location": //'${data[0]['start_address']}',
|
CRUD().post(link: '${AppLink.endPoint}/ride/rides/add.php', payload: {
|
||||||
'${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
|
"start_location": //'${data[0]['start_address']}',
|
||||||
"end_location": //'${data[0]['end_address']}',
|
'${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
|
||||||
'${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
|
"end_location": //'${data[0]['end_address']}',
|
||||||
"date": DateTime.now().toString(),
|
'${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
|
||||||
"time": DateTime.now().toString(),
|
"date": DateTime.now().toString(),
|
||||||
"endtime": durationToAdd.toString(),
|
"time": DateTime.now().toString(),
|
||||||
"price": totalPassenger.toStringAsFixed(2),
|
"endtime": durationToAdd.toString(),
|
||||||
"passenger_id": box.read(BoxName.passengerID).toString(),
|
"price": totalPassenger.toStringAsFixed(2),
|
||||||
"driver_id": dataCarsLocationByPassenger['data'][carsOrder]['driver_id']
|
"passenger_id": box.read(BoxName.passengerID).toString(),
|
||||||
.toString(),
|
"driver_id": dataCarsLocationByPassenger['data'][carsOrder]
|
||||||
"status": "waiting",
|
['driver_id']
|
||||||
'carType': box.read(BoxName.carType),
|
.toString(),
|
||||||
"price_for_driver": totalPassenger.toString(),
|
"status": "waiting",
|
||||||
"price_for_passenger": totalME.toString(),
|
'carType': box.read(BoxName.carType),
|
||||||
"distance": distance.toString(),
|
"price_for_driver": totalPassenger.toString(),
|
||||||
"paymentMethod": paymentController.isWalletChecked.toString(),
|
"price_for_passenger": totalME.toString(),
|
||||||
});
|
"distance": distance.toString(),
|
||||||
|
"paymentMethod": paymentController.isWalletChecked.toString(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
delayAndFetchRideStatusForAllDriverAvailable(rideId);
|
delayAndFetchRideStatusForAllDriverAvailable(rideId);
|
||||||
update();
|
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() {
|
icreaseForSameRideAndDelay() {
|
||||||
PaymentController paymentController = Get.find<PaymentController>();
|
PaymentController paymentController = Get.find<PaymentController>();
|
||||||
rideConfirm = true;
|
rideConfirm = true;
|
||||||
@@ -1398,19 +1768,20 @@ class MapPassengerController extends GetxController {
|
|||||||
String res = await getRideStatus(rideId);
|
String res = await getRideStatus(rideId);
|
||||||
|
|
||||||
Log.print('tick: $tick');
|
Log.print('tick: $tick');
|
||||||
|
String rideStatusDelayed = res.toString();
|
||||||
if ((res.toString() == 'waiting' || res.toString() == 'Refused') &&
|
if ((rideStatusDelayed == 'waiting' ||
|
||||||
|
rideStatusDelayed == 'Refused') &&
|
||||||
tick >= 15) {
|
tick >= 15) {
|
||||||
timer.cancel(); // Stop the current timer
|
timer.cancel(); // Stop the current timer
|
||||||
showAndResearchForCaptain();
|
showAndResearchForCaptain();
|
||||||
//TODO add to wait
|
//TODO add to wait
|
||||||
await getCarsLocationByPassengerAndReloadMarker(carType, 4500);
|
await getCarsLocationByPassengerAndReloadMarker(carType, 3000);
|
||||||
// await getNearestDriverByPassengerLocationAPIGOOGLE();
|
// await getNearestDriverByPassengerLocationAPIGOOGLE();
|
||||||
// getCarForFirstConfirm(carType);
|
// getCarForFirstConfirm(carType);
|
||||||
confirmRideForAllDriverAvailable();
|
confirmRideForAllDriverAvailable();
|
||||||
// delayAndFetchRideStatusForAllDriverAvailable(rideId);
|
// delayAndFetchRideStatusForAllDriverAvailable(rideId);
|
||||||
} else if (res.toString() == 'Apply') {
|
} else if (rideStatusDelayed == 'Apply') {
|
||||||
Log.print('res.toString() == Apply: ${res.toString()}');
|
Log.print('rideStatusDelayed == Apply: ${rideStatusDelayed}');
|
||||||
// todo play sound
|
// todo play sound
|
||||||
Get.find<AudioRecorderController>()
|
Get.find<AudioRecorderController>()
|
||||||
.playSoundFromAssets('assets/start.wav');
|
.playSoundFromAssets('assets/start.wav');
|
||||||
@@ -1422,7 +1793,7 @@ class MapPassengerController extends GetxController {
|
|||||||
isSearchingWindow = false;
|
isSearchingWindow = false;
|
||||||
update();
|
update();
|
||||||
startTimerFromDriverToPassengerAfterApplied();
|
startTimerFromDriverToPassengerAfterApplied();
|
||||||
} else if (res.toString() == 'Refused') {
|
} else if (rideStatusDelayed == 'Refused') {
|
||||||
statusRide = 'Refused';
|
statusRide = 'Refused';
|
||||||
if (isDriversTokensSend == false) {
|
if (isDriversTokensSend == false) {
|
||||||
confirmRideForAllDriverAvailable();
|
confirmRideForAllDriverAvailable();
|
||||||
@@ -1473,17 +1844,22 @@ class MapPassengerController extends GetxController {
|
|||||||
attemptCounter++;
|
attemptCounter++;
|
||||||
tick++;
|
tick++;
|
||||||
var res = await getRideStatus(rideId);
|
var res = await getRideStatus(rideId);
|
||||||
|
String rideStatusDelayed = res.toString();
|
||||||
|
|
||||||
if (res.toString() == 'Apply' || res.toString() == 'Applied') {
|
if (rideStatusDelayed == 'Apply' || rideStatusDelayed == 'Applied') {
|
||||||
await getUpdatedRideForDriverApply(rideId);
|
await getUpdatedRideForDriverApply(rideId);
|
||||||
isApplied = true;
|
isApplied = true;
|
||||||
shouldFetch = false;
|
shouldFetch = false;
|
||||||
statusRide = 'Apply';
|
statusRide = 'Apply';
|
||||||
rideConfirm = false;
|
rideConfirm = false;
|
||||||
isSearchingWindow = false;
|
isSearchingWindow = false;
|
||||||
|
|
||||||
|
startTimer();
|
||||||
|
|
||||||
update();
|
update();
|
||||||
startTimerFromDriverToPassengerAfterApplied();
|
startTimerFromDriverToPassengerAfterApplied();
|
||||||
} else if (attemptCounter >= maxAttempts && statusRide != 'Cancel') {
|
} else if (attemptCounter >= maxAttempts &&
|
||||||
|
rideStatusDelayed != 'Cancel') {
|
||||||
shouldFetch = false;
|
shouldFetch = false;
|
||||||
// If the status is still not "Apply" after 15 attempts
|
// If the status is still not "Apply" after 15 attempts
|
||||||
MyDialog().getDialog('upgrade price'.tr,
|
MyDialog().getDialog('upgrade price'.tr,
|
||||||
@@ -1573,7 +1949,7 @@ class MapPassengerController extends GetxController {
|
|||||||
|
|
||||||
reSearchAfterCanceledFromDriver() async {
|
reSearchAfterCanceledFromDriver() async {
|
||||||
await getCarsLocationByPassengerAndReloadMarker(
|
await getCarsLocationByPassengerAndReloadMarker(
|
||||||
box.read(BoxName.carType), 4500);
|
box.read(BoxName.carType), 3000);
|
||||||
|
|
||||||
confirmRideForAllDriverAvailable();
|
confirmRideForAllDriverAvailable();
|
||||||
shouldFetch = true; // Stop further fetches
|
shouldFetch = true; // Stop further fetches
|
||||||
@@ -1616,8 +1992,9 @@ class MapPassengerController extends GetxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<String> getRideStatus(String rideId) async {
|
Future<String> getRideStatus(String rideId) async {
|
||||||
final response =
|
final response = await CRUD().get(
|
||||||
await CRUD().get(link: AppLink.getRideStatus, payload: {'id': rideId});
|
link: "${AppLink.endPoint}/ride/rides/getRideStatus.php",
|
||||||
|
payload: {'id': rideId});
|
||||||
|
|
||||||
return jsonDecode(response)['data'];
|
return jsonDecode(response)['data'];
|
||||||
}
|
}
|
||||||
@@ -1638,7 +2015,7 @@ class MapPassengerController extends GetxController {
|
|||||||
make = response['data']['make'];
|
make = response['data']['make'];
|
||||||
licensePlate = response['data']['car_plate'];
|
licensePlate = response['data']['car_plate'];
|
||||||
firstName = response['data']['first_name'];
|
firstName = response['data']['first_name'];
|
||||||
driverName = response['data']['driverName'];
|
driverName = response['data']['driverName'].toString().split(' ')[0];
|
||||||
driverToken = response['data']['token'];
|
driverToken = response['data']['token'];
|
||||||
Log.print('driverToken updated: $driverToken');
|
Log.print('driverToken updated: $driverToken');
|
||||||
carYear = response['data']['year'];
|
carYear = response['data']['year'];
|
||||||
@@ -1646,10 +2023,11 @@ class MapPassengerController extends GetxController {
|
|||||||
}
|
}
|
||||||
// driversToken.remove(driverToken);
|
// driversToken.remove(driverToken);
|
||||||
// for (var i = 1; i < driversToken.length; i++) {
|
// for (var i = 1; i < driversToken.length; i++) {
|
||||||
FirebaseMessagesController().sendNotificationToAnyWithoutData(
|
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||||
'Order Applied'.tr,
|
'Order Applied'.tr,
|
||||||
'$driverName Apply order\nTake attention in other order'.tr,
|
'$driverName Apply order\nTake attention in other order'.tr,
|
||||||
driverToken,
|
driverToken,
|
||||||
|
[],
|
||||||
'start.wav',
|
'start.wav',
|
||||||
);
|
);
|
||||||
// }
|
// }
|
||||||
@@ -1871,6 +2249,7 @@ class MapPassengerController extends GetxController {
|
|||||||
longitude >= 31.215009 &&
|
longitude >= 31.215009 &&
|
||||||
longitude <= 31.532186) {
|
longitude <= 31.532186) {
|
||||||
box.write(BoxName.serverChosen, AppLink.seferCairoServer);
|
box.write(BoxName.serverChosen, AppLink.seferCairoServer);
|
||||||
|
|
||||||
return 'Cairo';
|
return 'Cairo';
|
||||||
} else if (latitude >= 29.904975 &&
|
} else if (latitude >= 29.904975 &&
|
||||||
latitude <= 30.143372 &&
|
latitude <= 30.143372 &&
|
||||||
@@ -2380,12 +2759,13 @@ class MapPassengerController extends GetxController {
|
|||||||
double tripDurationInMinutes = durationToRide / 6;
|
double tripDurationInMinutes = durationToRide / 6;
|
||||||
int loopCount = tripDurationInMinutes.ceil();
|
int loopCount = tripDurationInMinutes.ceil();
|
||||||
// If the trip duration is less than or equal to 50 minutes, then break the loop.
|
// If the trip duration is less than or equal to 50 minutes, then break the loop.
|
||||||
|
clearMarkersExceptStartEnd();
|
||||||
for (var i = 0; i < loopCount; i++) {
|
for (var i = 0; i < loopCount; i++) {
|
||||||
// Wait for 50 seconds.
|
// Wait for 50 seconds.
|
||||||
await Future.delayed(const Duration(seconds: 4));
|
await Future.delayed(const Duration(seconds: 4));
|
||||||
if (rideTimerBegin == true && statusRide == 'Apply') {
|
// if (rideTimerBegin == true && statusRide == 'Apply') {
|
||||||
await getDriverCarsLocationToPassengerAfterApplied();
|
await getDriverCarsLocationToPassengerAfterApplied();
|
||||||
}
|
// }
|
||||||
reloadMarkerDriverCarsLocationToPassengerAfterApplied();
|
reloadMarkerDriverCarsLocationToPassengerAfterApplied();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2517,79 +2897,66 @@ class MapPassengerController extends GetxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future cancelRide() async {
|
Future cancelRide() async {
|
||||||
if (rideConfirm == false && statusRide == 'Apply' ||
|
// if (rideConfirm == true ||
|
||||||
statusRide == 'Applied' ||
|
// statusRide == 'Apply' ||
|
||||||
statusRide == 'waiting') {
|
// statusRide == 'Applied' ||
|
||||||
clearPlacesDestination();
|
// statusRide == 'wait' ||
|
||||||
clearPolyline();
|
// statusRide == 'waiting') {
|
||||||
// clearPolylineAll();
|
clearPlacesDestination();
|
||||||
data = [];
|
clearPolyline();
|
||||||
changeCancelRidePageShow();
|
// clearPolylineAll();
|
||||||
if (rideId != 'yet') {
|
data = [];
|
||||||
await CRUD().post(link: AppLink.updateDriverOrder, payload: {
|
changeCancelRidePageShow();
|
||||||
"order_id": rideId.toString(), // Convert to String
|
if (rideId != 'yet') {
|
||||||
"status": 'Cancel'
|
Log.print('cancelRide: 1');
|
||||||
});
|
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||||
FirebaseMessagesController().sendNotificationToDriverMAP(
|
'Cancel Trip'.tr,
|
||||||
'Cancel Trip',
|
'Trip Cancelled'.tr,
|
||||||
'Trip Cancelled'.tr,
|
driverToken,
|
||||||
driverToken,
|
[],
|
||||||
[],
|
'cancel.wav',
|
||||||
'cancel.wav',
|
);
|
||||||
);
|
|
||||||
if (AppLink.endPoint != AppLink.seferCairoServer) {
|
await Future.wait([
|
||||||
CRUD().post(
|
CRUD().post(link: AppLink.updateRides, payload: {
|
||||||
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: {
|
|
||||||
"id": rideId.toString(), // Convert to String
|
"id": rideId.toString(), // Convert to String
|
||||||
"status": 'Cancel'
|
"status": 'Cancel'
|
||||||
});
|
}),
|
||||||
if (AppLink.endPoint != AppLink.seferCairoServer) {
|
CRUD().post(link: AppLink.updateDriverOrder, payload: {
|
||||||
CRUD().post(
|
"order_id": rideId.toString(), // Convert to String
|
||||||
link: "${AppLink.endPoint}/ride/rides/update.php",
|
"status": 'Cancel'
|
||||||
payload: {
|
}),
|
||||||
"id": rideId.toString(), // Convert to String
|
|
||||||
"status": 'Cancel'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
CRUD().post(link: AppLink.updateWaitingTrip, payload: {
|
CRUD().post(link: AppLink.updateWaitingTrip, payload: {
|
||||||
"id": rideId.toString(), // Convert to String
|
"id": rideId.toString(), // Convert to String
|
||||||
"status": 'Cancel'
|
"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(
|
||||||
CRUD().post(
|
link:
|
||||||
link:
|
"${AppLink.endPoint}/ride/notificationCaptain/updateWaitingTrip.php",
|
||||||
"${AppLink.endPoint}/ride/notificationCaptain/updateWaitingTrip.php",
|
payload: {
|
||||||
payload: {
|
"id": rideId.toString(), // Convert to String
|
||||||
"id": rideId.toString(), // Convert to String
|
"status": 'Cancel'
|
||||||
"status": 'Cancel'
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
print('Cancel');
|
|
||||||
}
|
}
|
||||||
|
print('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());
|
|
||||||
}
|
}
|
||||||
|
Future.delayed(const Duration(seconds: 1));
|
||||||
|
Get.offAll(() => const MapPagePassenger());
|
||||||
}
|
}
|
||||||
|
|
||||||
void changePickerShown() {
|
void changePickerShown() {
|
||||||
@@ -2942,28 +3309,28 @@ class MapPassengerController extends GetxController {
|
|||||||
? LatLng(_locationData.latitude!, _locationData.longitude!)
|
? LatLng(_locationData.latitude!, _locationData.longitude!)
|
||||||
: null)!;
|
: null)!;
|
||||||
getLocationArea(passengerLocation.latitude, passengerLocation.longitude);
|
getLocationArea(passengerLocation.latitude, passengerLocation.longitude);
|
||||||
|
Log.print('AppLink.endPoint: ${AppLink.endPoint}');
|
||||||
|
// Log.print('BoxName.serverChosen: ${box.read(BoxName.serverChosen)}');
|
||||||
|
|
||||||
newStartPointLocation = passengerLocation;
|
newStartPointLocation = passengerLocation;
|
||||||
|
Log.print('passengerLocation: ${passengerLocation}');
|
||||||
speed = _locationData.speed!;
|
speed = _locationData.speed!;
|
||||||
// //print location details
|
// //print location details
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
LatLngBounds calculateBounds(
|
LatLngBounds calculateBounds(double lat, double lng, double radiusInMeters) {
|
||||||
double centerLat, double centerLng, double radius) {
|
const double earthRadius = 6378137.0; // Earth's radius in meters
|
||||||
// double radius = 4000; // 10 km in meters
|
|
||||||
|
|
||||||
southwest = LatLng(
|
double latDelta = radiusInMeters / earthRadius * (180 / pi);
|
||||||
centerLat - (radius / 111000),
|
double lngDelta =
|
||||||
centerLng - (radius / (111000 * cos(centerLat))),
|
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;
|
GoogleMapController? mapController;
|
||||||
@@ -2992,8 +3359,6 @@ class MapPassengerController extends GetxController {
|
|||||||
bool reloadStartApp = false;
|
bool reloadStartApp = false;
|
||||||
int reloadCount = 0;
|
int reloadCount = 0;
|
||||||
startMarkerReloading() async {
|
startMarkerReloading() async {
|
||||||
Log.print('AppLink.endPoint: ${AppLink.endPoint}');
|
|
||||||
|
|
||||||
if (reloadStartApp == false) {
|
if (reloadStartApp == false) {
|
||||||
Timer.periodic(const Duration(seconds: 5), (timer) async {
|
Timer.periodic(const Duration(seconds: 5), (timer) async {
|
||||||
reloadCount++;
|
reloadCount++;
|
||||||
@@ -3233,7 +3598,7 @@ class MapPassengerController extends GetxController {
|
|||||||
remainingTime = 25; //to make cancel every call
|
remainingTime = 25; //to make cancel every call
|
||||||
// startCarLocationSearch(box.read(BoxName.carType));
|
// startCarLocationSearch(box.read(BoxName.carType));
|
||||||
await getCarsLocationByPassengerAndReloadMarker(
|
await getCarsLocationByPassengerAndReloadMarker(
|
||||||
box.read(BoxName.carType), 7000);
|
box.read(BoxName.carType), 5000);
|
||||||
// await getCarsLocationByPassengerAndReloadMarker();
|
// await getCarsLocationByPassengerAndReloadMarker();
|
||||||
var coordDestination = destination.split(',');
|
var coordDestination = destination.split(',');
|
||||||
double latPassengerDestination = double.parse(coordDestination[0]);
|
double latPassengerDestination = double.parse(coordDestination[0]);
|
||||||
@@ -4093,55 +4458,77 @@ class MapPassengerController extends GetxController {
|
|||||||
try {
|
try {
|
||||||
// Prepare trip data
|
// Prepare trip data
|
||||||
Map<String, dynamic> tripData = {
|
Map<String, dynamic> tripData = {
|
||||||
'id': driver['id'],
|
'id': driver['id'].toString(), // Ensure the id is a string
|
||||||
'phone': driver['phone'],
|
'phone': driver['phone'],
|
||||||
'gender': driver['gender'],
|
'gender': driver['gender'],
|
||||||
'name': driver['name'],
|
'name': driver['NAME'],
|
||||||
'name_english': driver['name_english'],
|
'name_english': driver['name_english'],
|
||||||
'address': driver['address'],
|
'address': driver['address'],
|
||||||
'religion': driver['religion'],
|
'religion': driver['religion'],
|
||||||
'age': driver['age'],
|
'age': driver['age'].toString(), // Convert age to String
|
||||||
'education': driver['education'],
|
'education': driver['education'],
|
||||||
'license_type': driver['license_type'],
|
'license_type': driver['license_type'],
|
||||||
'national_number': driver['national_number'],
|
'national_number': driver['national_number'],
|
||||||
'car_plate': driver['car_plate'],
|
'car_plate': driver['car_plate'],
|
||||||
'make': driver['make'],
|
'make': driver['make'],
|
||||||
'model': driver['model'],
|
'model': driver['model'],
|
||||||
'year': driver['year'],
|
'year': driver['year'].toString(), // Convert year to String
|
||||||
'color': driver['color'],
|
'color': driver['color'],
|
||||||
'color_hex': driver['color_hex'],
|
'color_hex': driver['color_hex'],
|
||||||
'displacement': driver['displacement'],
|
'displacement': driver['displacement'],
|
||||||
'fuel': driver['fuel'],
|
'fuel': driver['fuel'],
|
||||||
'token': driver['token'],
|
'token': driver['token'],
|
||||||
'rating': driver['rating'],
|
'rating': driver['rating'].toString(), // Convert rating to String
|
||||||
'countRide': driver['countRide'],
|
'countRide':
|
||||||
|
driver['countRide'].toString(), // Convert countRide to String
|
||||||
'passengerId': box.read(BoxName.passengerID),
|
'passengerId': box.read(BoxName.passengerID),
|
||||||
'timeSelected': tripDateTime.toIso8601String(),
|
'timeSelected': tripDateTime.toIso8601String(),
|
||||||
'status': 'pending', // Or other appropriate status
|
'status': 'pending',
|
||||||
};
|
};
|
||||||
|
// Log.print('tripData: $tripData');
|
||||||
|
|
||||||
// Send data to server
|
// Send data to server
|
||||||
var response =
|
var response =
|
||||||
await CRUD().post(link: AppLink.addMishwari, payload: tripData);
|
await CRUD().post(link: AppLink.addMishwari, payload: tripData);
|
||||||
|
// Log.print('response: $response');
|
||||||
|
|
||||||
if (response != 'failure') {
|
if (response != 'failure') {
|
||||||
// Trip saved successfully
|
// Trip saved successfully
|
||||||
Get.snackbar('Success'.tr, 'Trip booked successfully'.tr);
|
Get.snackbar('Success'.tr, 'Trip booked successfully'.tr);
|
||||||
|
var id = response['message'].toString();
|
||||||
if (AppLink.endPoint != AppLink.seferCairoServer) {
|
if (AppLink.endPoint != AppLink.seferCairoServer) {
|
||||||
CRUD().post(
|
await CRUD().post(
|
||||||
link: "${AppLink.endPoint}/ride/mishwari/add.php",
|
link: "${AppLink.endPoint}/ride/mishwari/add.php",
|
||||||
payload: tripData);
|
payload: tripData);
|
||||||
}
|
}
|
||||||
// Set up local notification
|
// Optionally, set up local notification or send a push notification
|
||||||
// await setLocalNotification(tripDateTime);
|
// await setLocalNotification(tripDateTime);
|
||||||
|
await FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||||
// Send notification to driver
|
'OrderVIP',
|
||||||
// await FirebaseMessagesController().sendNotificationToDriverMAP();
|
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 {
|
} else {
|
||||||
throw Exception('Failed to save trip');
|
throw Exception('Failed to save trip');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} 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();
|
addCustomStepIcon();
|
||||||
addCustomStartIcon();
|
addCustomStartIcon();
|
||||||
addCustomEndIcon();
|
addCustomEndIcon();
|
||||||
addToken();
|
// addToken();
|
||||||
getLocation();
|
await getLocation();
|
||||||
getPassengerLocationUniversity();
|
getPassengerLocationUniversity();
|
||||||
_initializePolygons();
|
_initializePolygons();
|
||||||
// await addToken();
|
// await addToken();
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:SEFER/views/widgets/my_dialog.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:SEFER/constant/box_name.dart';
|
import 'package:SEFER/constant/box_name.dart';
|
||||||
import 'package:SEFER/constant/colors.dart';
|
import 'package:SEFER/constant/colors.dart';
|
||||||
import 'package:SEFER/constant/links.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/controller/functions/crud.dart';
|
||||||
import 'package:SEFER/main.dart';
|
import 'package:SEFER/main.dart';
|
||||||
import 'package:SEFER/views/widgets/elevated_btn.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 {
|
class ComplaintController extends GetxController {
|
||||||
bool isLoading = false;
|
bool isLoading = false;
|
||||||
final formKey = GlobalKey<FormState>();
|
final formKey = GlobalKey<FormState>();
|
||||||
final complaintController = TextEditingController();
|
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 {
|
void addComplaint() async {
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
@@ -34,11 +64,175 @@ class ComplaintController extends GetxController {
|
|||||||
title: 'Ok'.tr,
|
title: 'Ok'.tr,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back();
|
Get.back();
|
||||||
Get.back();
|
// Get.back();
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
update();
|
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 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:SEFER/constant/box_name.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:SEFER/constant/links.dart';
|
import 'package:SEFER/constant/links.dart';
|
||||||
import 'package:SEFER/constant/style.dart';
|
|
||||||
import 'package:SEFER/controller/functions/crud.dart';
|
import 'package:SEFER/controller/functions/crud.dart';
|
||||||
import 'package:SEFER/views/widgets/elevated_btn.dart';
|
|
||||||
|
import '../../../main.dart';
|
||||||
|
|
||||||
class PromosController extends GetxController {
|
class PromosController extends GetxController {
|
||||||
List<dynamic> promoList = [];
|
List<dynamic> promoList = [];
|
||||||
@@ -17,7 +18,9 @@ class PromosController extends GetxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future getPromoByToday() async {
|
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') {
|
if (res.toString() == 'failure') {
|
||||||
// Get.defaultDialog(
|
// Get.defaultDialog(
|
||||||
// title: 'No Promo for today .'.tr,
|
// title: 'No Promo for today .'.tr,
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ class LocaleController extends GetxController {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
String storedLang = box.read(BoxName.lang) ?? "";
|
String storedLang = box.read(BoxName.lang) ?? "ar";
|
||||||
switch (storedLang) {
|
switch (storedLang) {
|
||||||
case "ar":
|
case "ar":
|
||||||
language = const Locale("ar");
|
language = const Locale("ar");
|
||||||
|
|||||||
@@ -56,8 +56,7 @@ class MyTranslation extends Translations {
|
|||||||
"I want to order for someone else": "أريد أن أطلب لشخص آخر",
|
"I want to order for someone else": "أريد أن أطلب لشخص آخر",
|
||||||
"Cancel Trip from driver": "إلغاء الرحلة من السائق",
|
"Cancel Trip from driver": "إلغاء الرحلة من السائق",
|
||||||
"If you want order to another person": "إذا كنت تريد الطلب لشخص آخر",
|
"If you want order to another person": "إذا كنت تريد الطلب لشخص آخر",
|
||||||
"We will look for a new driver.\nPlease wait.":
|
|
||||||
"سنبحث عن سائق جديد.\nمن فضلك انتظر.",
|
|
||||||
"upgrade price": "رفع السعر",
|
"upgrade price": "رفع السعر",
|
||||||
'airport': 'مطار',
|
'airport': 'مطار',
|
||||||
"Best choice for a comfortable car with a flexible route and stop points. This airport offers visa entry at this price.":
|
"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":
|
"Capture an Image of Your ID Document front":
|
||||||
"التقط صورة للواجهة الأمامية لوثيقة هويتك",
|
"التقط صورة للواجهة الأمامية لوثيقة هويتك",
|
||||||
"NationalID": "الرقم القومي",
|
"NationalID": "الرقم القومي",
|
||||||
|
'You can share the SEFER App with your friends and earn rewards for rides they take using your code':
|
||||||
|
'يمكنك مشاركة تطبيق SEFER مع أصدقائك وكسب مكافآت من الرحلات التي يقومون بها باستخدام كودك.',
|
||||||
"FullName": "الاسم الكامل",
|
"FullName": "الاسم الكامل",
|
||||||
|
"No invitation found yet!": "لم يتم العثور على دعوات حتى الآن!",
|
||||||
"InspectionResult": "نتيجة الفحص",
|
"InspectionResult": "نتيجة الفحص",
|
||||||
"Criminal Record": "السجل الجنائي",
|
"Criminal Record": "السجل الجنائي", 'Share App': 'شارك التطبيق',
|
||||||
"The email or phone number is already registered.":
|
"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.':
|
'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": "فحص الوثائق",
|
"Documents check": "فحص الوثائق",
|
||||||
"Driver's License": "رخصة القيادة",
|
"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": "نوع الرخصة",
|
"License Type": "نوع الرخصة",
|
||||||
"National Number": "الرقم الوطني",
|
"National Number": "الرقم الوطني",
|
||||||
"Name (Arabic)": "الاسم بالعربي",
|
"Name (Arabic)": "الاسم بالعربي",
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:SEFER/constant/colors.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:SEFER/constant/box_name.dart';
|
import 'package:SEFER/constant/box_name.dart';
|
||||||
@@ -48,40 +50,41 @@ class ProfileController extends GetxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updatField(String columnName, TextInputType type) async {
|
updatField(String columnName, TextInputType type) async {
|
||||||
Get.defaultDialog(
|
Get.dialog(
|
||||||
title: '${'Update'.tr} $columnName',
|
CupertinoAlertDialog(
|
||||||
content: Column(
|
title: Text('${'Update'.tr} $columnName'),
|
||||||
children: [
|
content: Column(
|
||||||
SizedBox(
|
children: [
|
||||||
width: Get.width * .7,
|
const SizedBox(height: 16), // Add spacing between title and input
|
||||||
child: MyTextForm(
|
CupertinoTextField(
|
||||||
controller: txtController,
|
controller: txtController,
|
||||||
label: 'type here'.tr,
|
placeholder: 'type here'.tr,
|
||||||
hint: 'type here',
|
keyboardType: type,
|
||||||
type: type)
|
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
|
||||||
// TextField(
|
decoration: BoxDecoration(
|
||||||
// controller: txtController,
|
border: Border.all(color: CupertinoColors.lightBackgroundGray),
|
||||||
// decoration: const InputDecoration(
|
borderRadius: BorderRadius.circular(8),
|
||||||
// border: OutlineInputBorder(), hintText: 'type here'),
|
|
||||||
// ),
|
|
||||||
|
|
||||||
),
|
),
|
||||||
MyElevatedButton(
|
),
|
||||||
title: 'Update'.tr,
|
const SizedBox(height: 20),
|
||||||
onPressed: () async {
|
CupertinoButton(
|
||||||
Get.back();
|
color: AppColor.blueColor,
|
||||||
await updateColumn({
|
onPressed: () async {
|
||||||
'id': box.read(BoxName.passengerID),
|
Get.back();
|
||||||
columnName: txtController.text,
|
await updateColumn({
|
||||||
});
|
'id': box.read(BoxName.passengerID),
|
||||||
if (columnName == 'first_name') {
|
columnName: txtController.text,
|
||||||
box.write(BoxName.name, 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,
|
'token': token1,
|
||||||
});
|
});
|
||||||
if (res != 'failure') {
|
if (res != 'failure') {
|
||||||
FirebaseMessagesController().sendNotificationToAnyWithoutData(
|
FirebaseMessagesController().sendNotificationToDriverMAP(
|
||||||
'You Have Tips'.tr,
|
'You Have Tips'.tr,
|
||||||
'${'${tip.toString()}\$${' tips\nTotal is'.tr}'} ${tip + (Get.find<MapPassengerController>().totalPassenger)}',
|
'${'${tip.toString()}\$${' tips\nTotal is'.tr}'} ${tip + (Get.find<MapPassengerController>().totalPassenger)}',
|
||||||
Get.find<MapPassengerController>().driverToken.toString(),
|
Get.find<MapPassengerController>().driverToken.toString(),
|
||||||
|
[],
|
||||||
'ding.wav',
|
'ding.wav',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:SEFER/controller/payment/paymob/paymob_response.dart';
|
import 'package:SEFER/controller/payment/paymob/paymob_response.dart';
|
||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
@@ -12,6 +13,7 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
import 'package:wakelock_plus/wakelock_plus.dart';
|
||||||
import 'constant/api_key.dart';
|
import 'constant/api_key.dart';
|
||||||
import 'constant/info.dart';
|
import 'constant/info.dart';
|
||||||
|
import 'constant/notification.dart';
|
||||||
import 'controller/firebase/firbase_messge.dart';
|
import 'controller/firebase/firbase_messge.dart';
|
||||||
import 'controller/firebase/local_notification.dart';
|
import 'controller/firebase/local_notification.dart';
|
||||||
import 'controller/local/local_controller.dart';
|
import 'controller/local/local_controller.dart';
|
||||||
@@ -40,10 +42,24 @@ void main() async {
|
|||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
WakelockPlus.enable();
|
WakelockPlus.enable();
|
||||||
// await LocationController().startLocationUpdates();
|
// await LocationController().startLocationUpdates();
|
||||||
if (Platform.isAndroid) {
|
// if (Platform.isAndroid) {
|
||||||
await NotificationController().initNotifications();
|
NotificationController notificationController =
|
||||||
}
|
Get.put(NotificationController());
|
||||||
|
await notificationController.initNotifications();
|
||||||
|
|
||||||
|
// Generate a random index to pick a message
|
||||||
|
final random = Random();
|
||||||
|
final randomMessage = messages[random.nextInt(messages.length)];
|
||||||
|
|
||||||
|
// Schedule the notification with the random message
|
||||||
|
notificationController.scheduleDailyNotifications(
|
||||||
|
randomMessage.split(':')[0],
|
||||||
|
randomMessage.split(':')[1],
|
||||||
|
"ding",
|
||||||
|
);
|
||||||
|
|
||||||
|
// await NotificationController().initNotifications();
|
||||||
|
// }
|
||||||
await GetStorage.init();
|
await GetStorage.init();
|
||||||
// Get.put(DriverCallController());
|
// Get.put(DriverCallController());
|
||||||
// await AC().gAK();
|
// await AC().gAK();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class SmsSignupEgypt extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Get.put(RegisterController());
|
Get.put(RegisterController());
|
||||||
return MyScafolld(
|
return MyScafolld(
|
||||||
title: 'Phone Check'.tr,
|
title: "Phone Number Check".tr,
|
||||||
body: [
|
body: [
|
||||||
GetBuilder<RegisterController>(builder: (registerController) {
|
GetBuilder<RegisterController>(builder: (registerController) {
|
||||||
return ListView(
|
return ListView(
|
||||||
@@ -99,13 +99,16 @@ class SmsSignupEgypt extends StatelessWidget {
|
|||||||
// Submit button
|
// Submit button
|
||||||
registerController.isLoading
|
registerController.isLoading
|
||||||
? const MyCircularProgressIndicator()
|
? const MyCircularProgressIndicator()
|
||||||
: MyElevatedButton(
|
: Padding(
|
||||||
onPressed: () async {
|
padding: const EdgeInsets.all(16.0),
|
||||||
!registerController.isSent
|
child: MyElevatedButton(
|
||||||
? await registerController.sendOtpMessage()
|
onPressed: () async {
|
||||||
: await registerController.verifySMSCode();
|
!registerController.isSent
|
||||||
},
|
? await registerController.sendOtpMessage()
|
||||||
title: 'Submit'.tr,
|
: await registerController.verifySMSCode();
|
||||||
|
},
|
||||||
|
title: 'Submit'.tr,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,101 +1,153 @@
|
|||||||
import 'package:SEFER/constant/box_name.dart';
|
import 'package:SEFER/constant/box_name.dart';
|
||||||
import 'package:SEFER/constant/style.dart';
|
|
||||||
import 'package:SEFER/main.dart';
|
import 'package:SEFER/main.dart';
|
||||||
import 'package:SEFER/views/widgets/my_scafold.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
|
||||||
class AboutPage extends StatelessWidget {
|
class AboutPage extends StatelessWidget {
|
||||||
const AboutPage({super.key});
|
const AboutPage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MyScafolld(
|
return CupertinoPageScaffold(
|
||||||
title: 'About Us'.tr,
|
navigationBar: CupertinoNavigationBar(
|
||||||
body: [
|
middle: Text('About Us'.tr),
|
||||||
// Company Logo (consider adding an image asset)
|
),
|
||||||
ListView(
|
child: SafeArea(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
|
// Company Logo
|
||||||
Center(
|
Center(
|
||||||
child: Image.asset(
|
child: Padding(
|
||||||
'assets/images/logo.png', // Replace with your logo image asset path
|
padding: const EdgeInsets.all(16.0),
|
||||||
height: 100.0,
|
child: Image.asset(
|
||||||
width: 100.0,
|
'assets/images/logo.png', // Replace with your logo image asset path
|
||||||
|
height: 100.0,
|
||||||
|
width: 100.0,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
), // Company Name and Location
|
),
|
||||||
|
|
||||||
|
// Company Name and Location
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
'SEFER LLC\n${box.read(BoxName.countryCode).toString().tr}',
|
'SEFER LLC\n${box.read(BoxName.countryCode).toString().tr}',
|
||||||
style: AppStyle.headTitle2,
|
style:
|
||||||
|
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
||||||
|
fontSize: 22.0,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// About Us Description
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
'SEFER is a ride-sharing app designed with your safety and affordability in mind. We connect you with reliable drivers in your area, ensuring a convenient and stress-free travel experience.\n\nHere are some of the key features that set us apart:'
|
'SEFER is a ride-sharing app designed with your safety and affordability in mind. We connect you with reliable drivers in your area, ensuring a convenient and stress-free travel experience.\n\nHere are some of the key features that set us apart:'
|
||||||
.tr,
|
.tr,
|
||||||
style: AppStyle.title,
|
style:
|
||||||
|
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
||||||
|
fontSize: 16.0,
|
||||||
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
), // Security Features List
|
|
||||||
const SizedBox(
|
|
||||||
height: 20,
|
|
||||||
),
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
|
// Security Features
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.lock, color: Colors.blue),
|
const Icon(CupertinoIcons.lock_fill,
|
||||||
|
color: CupertinoColors.activeBlue),
|
||||||
const SizedBox(width: 8.0),
|
const SizedBox(width: 8.0),
|
||||||
Text(
|
Expanded(
|
||||||
'Most Secure Methods'.tr,
|
child: Text(
|
||||||
style: AppStyle.title,
|
'Most Secure Methods'.tr,
|
||||||
|
style: CupertinoTheme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.textStyle
|
||||||
|
.copyWith(
|
||||||
|
fontSize: 16.0,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8.0),
|
const SizedBox(height: 8.0),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.phone, color: Colors.blue),
|
const Icon(CupertinoIcons.phone_fill,
|
||||||
|
color: CupertinoColors.activeBlue),
|
||||||
const SizedBox(width: 8.0),
|
const SizedBox(width: 8.0),
|
||||||
Text(
|
Expanded(
|
||||||
'In-App VOIP Calls'.tr,
|
child: Text(
|
||||||
style: AppStyle.title,
|
'In-App VOIP Calls'.tr,
|
||||||
|
style: CupertinoTheme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.textStyle
|
||||||
|
.copyWith(
|
||||||
|
fontSize: 16.0,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8.0),
|
const SizedBox(height: 8.0),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.videocam, color: Colors.blue),
|
const Icon(CupertinoIcons.videocam_fill,
|
||||||
|
color: CupertinoColors.activeBlue),
|
||||||
const SizedBox(width: 8.0),
|
const SizedBox(width: 8.0),
|
||||||
Text(
|
Expanded(
|
||||||
'Recorded Trips for Safety'.tr,
|
child: Text(
|
||||||
style: AppStyle.title,
|
'Recorded Trips for Safety'.tr,
|
||||||
|
style: CupertinoTheme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.textStyle
|
||||||
|
.copyWith(
|
||||||
|
fontSize: 16.0,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
), // Affordability Highlight
|
),
|
||||||
|
|
||||||
|
// Affordability Highlight
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
'\nWe also prioritize affordability, offering competitive pricing to make your rides accessible.'
|
'\nWe also prioritize affordability, offering competitive pricing to make your rides accessible.'
|
||||||
.tr,
|
.tr,
|
||||||
style: AppStyle.title,
|
style:
|
||||||
|
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
||||||
|
fontSize: 16.0,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 20),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
// About Us Text
|
),
|
||||||
],
|
);
|
||||||
isleading: true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
437
lib/views/home/HomePage/share_app_page.dart
Normal file
437
lib/views/home/HomePage/share_app_page.dart
Normal file
@@ -0,0 +1,437 @@
|
|||||||
|
import 'package:SEFER/constant/style.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
import '../../../constant/box_name.dart';
|
||||||
|
import '../../../constant/colors.dart';
|
||||||
|
import '../../../controller/home/profile/invit_controller.dart';
|
||||||
|
import '../../../main.dart';
|
||||||
|
|
||||||
|
class ShareAppPage extends StatelessWidget {
|
||||||
|
final InviteController controller = Get.put(InviteController());
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: CupertinoColors.systemBackground,
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: CupertinoColors.systemBackground,
|
||||||
|
elevation: 0,
|
||||||
|
title: Text(
|
||||||
|
'Invite'.tr,
|
||||||
|
style: const TextStyle(color: CupertinoColors.label),
|
||||||
|
),
|
||||||
|
leading: IconButton(
|
||||||
|
icon: const Icon(Icons.arrow_back_ios, color: AppColor.blueColor),
|
||||||
|
onPressed: () => Get.back(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: SafeArea(
|
||||||
|
child: GetBuilder<InviteController>(
|
||||||
|
builder: (controller) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: _buildPassengerTab(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildPassengerTab(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: CupertinoColors.systemGrey6,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Share this code with your friends and earn rewards when they use it!"
|
||||||
|
.tr,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: CupertinoColors.secondaryLabel,
|
||||||
|
fontSize: 13,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
_buildPhoneInput(),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
_buildActionButtonsPassengers(),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
_buildInvitationsListPassengers(context),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildPhoneInput() {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: CupertinoColors.systemGrey6,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: CupertinoTextField.borderless(
|
||||||
|
controller: controller.invitePhoneController,
|
||||||
|
placeholder: 'Enter phone'.tr,
|
||||||
|
padding: const EdgeInsets.all(12),
|
||||||
|
keyboardType: TextInputType.phone,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
CupertinoButton(
|
||||||
|
child: const Icon(CupertinoIcons.person_badge_plus,
|
||||||
|
color: AppColor.blueColor),
|
||||||
|
onPressed: () async {
|
||||||
|
await controller.pickContacts();
|
||||||
|
if (controller.contacts.isNotEmpty) {
|
||||||
|
if (box.read(BoxName.isSavedPhones) == null) {
|
||||||
|
controller.savePhoneToServer();
|
||||||
|
box.write(BoxName.isSavedPhones, true);
|
||||||
|
}
|
||||||
|
_showContactsDialog(Get.context!);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildActionButtonsPassengers() {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 20.0, horizontal: 16.0),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.1),
|
||||||
|
blurRadius: 6,
|
||||||
|
offset: const Offset(0, 3),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: CupertinoButton(
|
||||||
|
color: AppColor.blueColor,
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||||
|
onPressed: controller.sendInviteToPassenger,
|
||||||
|
child: Text(
|
||||||
|
'Send Invite'.tr,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: CupertinoColors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.1),
|
||||||
|
blurRadius: 6,
|
||||||
|
offset: const Offset(0, 3),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: CupertinoButton(
|
||||||
|
color: AppColor.blueColor,
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||||
|
child: Text(
|
||||||
|
'Show Invitations'.tr,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: CupertinoColors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () async {
|
||||||
|
controller.fetchDriverStatsPassengers();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildInvitationsListPassengers(BuildContext context) {
|
||||||
|
return SizedBox(
|
||||||
|
height: Get.height * .4,
|
||||||
|
child: controller.driverInvitationDataToPassengers.isEmpty
|
||||||
|
? Center(
|
||||||
|
child: Text(
|
||||||
|
"No invitation found yet!".tr,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: CupertinoColors.secondaryLabel,
|
||||||
|
fontSize: 17,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: ListView.builder(
|
||||||
|
itemCount: controller.driverInvitationDataToPassengers.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return _buildInvitationItemPassengers(context, index);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildInvitationItemPassengers(BuildContext context, int index) {
|
||||||
|
// Extracting the data from the sample JSON-like structure
|
||||||
|
var invitation = controller.driverInvitationDataToPassengers[index];
|
||||||
|
|
||||||
|
int countOfInvitDriver =
|
||||||
|
int.tryParse(invitation['countOfInvitDriver']?.toString() ?? '0') ?? 0;
|
||||||
|
double progressValue = (countOfInvitDriver / 10.0).clamp(0.0, 1.0);
|
||||||
|
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
controller.onSelectPassengerInvitation(index);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: CupertinoColors.systemGrey6,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
invitation['passengerName']
|
||||||
|
.toString(), // Handle null or missing data
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 17,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: CupertinoColors.label,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
|
child: LinearProgressIndicator(
|
||||||
|
value: progressValue,
|
||||||
|
backgroundColor: CupertinoColors.systemGrey4,
|
||||||
|
valueColor:
|
||||||
|
const AlwaysStoppedAnimation<Color>(AppColor.blueColor),
|
||||||
|
minHeight: 6,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
'$countOfInvitDriver / 2 ${'Trip'.tr}', // Show trips completed
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
color: CupertinoColors.secondaryLabel,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildPassengerStats(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: CupertinoColors.systemGrey6,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Your Rewards".tr,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 17,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: CupertinoColors.label,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
_buildStatItem(
|
||||||
|
context,
|
||||||
|
"Total Invites".tr,
|
||||||
|
controller.driverInvitationDataToPassengers[0]['countOfInvitDriver']
|
||||||
|
.toString(),
|
||||||
|
),
|
||||||
|
_buildStatItem(
|
||||||
|
context,
|
||||||
|
"Active Users".tr,
|
||||||
|
controller.driverInvitationDataToPassengers[0]['passengerName']
|
||||||
|
.toString(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildStatItem(BuildContext context, String label, String value) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
label,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: CupertinoColors.label,
|
||||||
|
fontSize: 15,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
value,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: AppColor.blueColor,
|
||||||
|
fontSize: 15,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showContactsDialog(BuildContext context) {
|
||||||
|
showCupertinoModalPopup(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) => Container(
|
||||||
|
height: 400,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: CupertinoColors.systemBackground,
|
||||||
|
borderRadius: const BorderRadius.vertical(top: Radius.circular(20)),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: CupertinoColors.black.withOpacity(0.2),
|
||||||
|
offset: const Offset(0, -4),
|
||||||
|
blurRadius: 10,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
// Header with cancel and title
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
||||||
|
color: CupertinoColors.systemGrey6,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
CupertinoButton(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
child: Text(
|
||||||
|
'Cancel'.tr,
|
||||||
|
style: const TextStyle(color: CupertinoColors.systemBlue),
|
||||||
|
),
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
child: Text('Choose from contact'.tr,
|
||||||
|
style: AppStyle.title)),
|
||||||
|
const SizedBox(width: 60), // Balance for Cancel button
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// Contact list
|
||||||
|
Expanded(
|
||||||
|
child: ListView.builder(
|
||||||
|
itemCount: controller.contactMaps.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final contact = controller.contactMaps[index];
|
||||||
|
return CupertinoButton(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
onPressed: () {
|
||||||
|
controller.selectPhone(contact['phones'].toString());
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 16, vertical: 12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: CupertinoColors.systemBackground,
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: CupertinoColors.separator.withOpacity(0.5),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
// Display contact name and phone number
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
contact['name'],
|
||||||
|
style: const TextStyle(
|
||||||
|
color: CupertinoColors.label,
|
||||||
|
fontSize: 17,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
controller.formatPhoneNumber(
|
||||||
|
contact['phones'][0].toString()),
|
||||||
|
style: const TextStyle(
|
||||||
|
color: CupertinoColors.secondaryLabel,
|
||||||
|
fontSize: 15,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Chevron icon for selection
|
||||||
|
const Icon(
|
||||||
|
CupertinoIcons.chevron_forward,
|
||||||
|
color: CupertinoColors.systemGrey2,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,11 @@
|
|||||||
import 'package:SEFER/views/widgets/my_scafold.dart';
|
import 'package:SEFER/views/widgets/my_scafold.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:share/share.dart';
|
import 'package:share/share.dart';
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
import '../../../constant/colors.dart';
|
|
||||||
import '../../../constant/style.dart';
|
|
||||||
import '../../../controller/functions/audio_record1.dart';
|
import '../../../controller/functions/audio_record1.dart';
|
||||||
import '../../../controller/functions/tts.dart';
|
|
||||||
import '../../widgets/elevated_btn.dart';
|
|
||||||
|
|
||||||
class TripsRecordedPage extends StatelessWidget {
|
class TripsRecordedPage extends StatelessWidget {
|
||||||
const TripsRecordedPage({
|
const TripsRecordedPage({
|
||||||
@@ -21,132 +18,193 @@ class TripsRecordedPage extends StatelessWidget {
|
|||||||
title: 'Trips recorded'.tr,
|
title: 'Trips recorded'.tr,
|
||||||
body: [
|
body: [
|
||||||
GetBuilder<AudioRecorderController>(builder: (audio) {
|
GetBuilder<AudioRecorderController>(builder: (audio) {
|
||||||
return Column(
|
return SingleChildScrollView(
|
||||||
children: [
|
child: Column(
|
||||||
FutureBuilder<List<String>>(
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
future: audio.getRecordedFiles(),
|
children: [
|
||||||
builder: (context, snapshot) {
|
FutureBuilder<List<String>>(
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
future: audio.getRecordedFiles(),
|
||||||
return const CircularProgressIndicator();
|
builder: (context, snapshot) {
|
||||||
} else if (snapshot.hasData) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
final recordedFiles = snapshot.data!;
|
return const Center(
|
||||||
return DropdownButton<String>(
|
child: CupertinoActivityIndicator());
|
||||||
value: audio.selectedFilePath,
|
} else if (snapshot.hasData) {
|
||||||
onChanged: (value) {
|
final recordedFiles = snapshot.data!;
|
||||||
audio.selectedFilePath = value;
|
return Padding(
|
||||||
audio.playRecordedFile(value!);
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
audio.update();
|
child: CupertinoButton(
|
||||||
},
|
padding: EdgeInsets.zero,
|
||||||
items: recordedFiles
|
|
||||||
.map((file) => DropdownMenuItem<String>(
|
|
||||||
value: file,
|
|
||||||
child: Text(path.basename(file)),
|
|
||||||
))
|
|
||||||
.toList(),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Text('Error: ${snapshot.error}');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Slider(
|
|
||||||
value: audio.currentPosition,
|
|
||||||
max: audio.totalDuration,
|
|
||||||
inactiveColor: AppColor.accentColor,
|
|
||||||
label: audio.currentPosition.toString(),
|
|
||||||
onChanged: (value) {
|
|
||||||
audio.currentPosition = value;
|
|
||||||
audio.audioPlayer.seek(Duration(seconds: value.toInt()));
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
||||||
children: [
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(
|
|
||||||
audio.isPlaying ? Icons.pause : Icons.play_arrow),
|
|
||||||
onPressed: () {
|
|
||||||
if (audio.isPlaying) {
|
|
||||||
audio.pausePlayback();
|
|
||||||
} else {
|
|
||||||
audio.resumePlayback();
|
|
||||||
}
|
|
||||||
audio.update();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.stop),
|
|
||||||
onPressed: () {
|
|
||||||
audio.stopPlayback();
|
|
||||||
audio.update();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.delete),
|
|
||||||
onPressed: () async {
|
|
||||||
Get.defaultDialog(
|
|
||||||
title: 'Are you sure to delete recorded files'.tr,
|
|
||||||
content: Column(
|
|
||||||
children: [
|
|
||||||
IconButton(
|
|
||||||
onPressed: () {
|
|
||||||
Get.find<TextToSpeechController>().speakText(
|
|
||||||
'this will delete all files from your device'
|
|
||||||
.tr);
|
|
||||||
},
|
|
||||||
icon: const Icon(Icons.headphones),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'this will delete all files from your device'
|
|
||||||
.tr,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: AppStyle.title,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
titleStyle: AppStyle.title,
|
|
||||||
confirm: MyElevatedButton(
|
|
||||||
title: 'Delete'.tr,
|
|
||||||
kolor: AppColor.redColor,
|
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await audio.deleteAllRecordedFiles();
|
String? selectedFile =
|
||||||
Get.back();
|
await showCupertinoModalPopup<String>(
|
||||||
Get.back();
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return CupertinoActionSheet(
|
||||||
|
title: Text('Select a File'.tr),
|
||||||
|
actions: recordedFiles
|
||||||
|
.map(
|
||||||
|
(file) => CupertinoActionSheetAction(
|
||||||
|
child: Text(path.basename(file)),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop(file);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (selectedFile != null) {
|
||||||
|
audio.selectedFilePath = selectedFile;
|
||||||
|
audio.playRecordedFile(selectedFile);
|
||||||
|
audio.update();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
child: Text(
|
||||||
|
audio.selectedFilePath != null
|
||||||
|
? path.basename(audio.selectedFilePath!)
|
||||||
|
: 'Select a File'.tr,
|
||||||
|
style: CupertinoTheme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.actionTextStyle
|
||||||
|
.copyWith(color: CupertinoColors.activeBlue),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Text('Error: ${snapshot.error}'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
// Cupertino-style slider for seeking audio
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
|
child: CupertinoSlider(
|
||||||
|
value: audio.totalDuration > 0
|
||||||
|
? audio.currentPosition / audio.totalDuration
|
||||||
|
: 0.0, // Normalize to a value between 0.0 and 1.0
|
||||||
|
min: 0.0,
|
||||||
|
max: 1.0, // Maximum value is now 1.0
|
||||||
|
activeColor: CupertinoColors.activeBlue,
|
||||||
|
onChanged: (value) {
|
||||||
|
final newPosition = value * audio.totalDuration;
|
||||||
|
audio.currentPosition = newPosition;
|
||||||
|
audio.audioPlayer
|
||||||
|
.seek(Duration(seconds: newPosition.toInt()));
|
||||||
|
audio.update();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
|
||||||
Align(
|
// iOS-style playback controls
|
||||||
alignment: Alignment.bottomCenter,
|
Padding(
|
||||||
child: Container(
|
padding: const EdgeInsets.symmetric(
|
||||||
padding: const EdgeInsets.all(16.0),
|
vertical: 16.0, horizontal: 16.0),
|
||||||
color: Colors.grey[200],
|
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
CupertinoButton(
|
||||||
audio.selectedFilePath != null
|
padding: EdgeInsets.zero,
|
||||||
? '${'Selected file:'.tr} ${path.basename(audio.selectedFilePath!)}'
|
child: Icon(
|
||||||
: 'No file selected'.tr,
|
audio.isPlaying
|
||||||
style: AppStyle.subtitle,
|
? CupertinoIcons.pause
|
||||||
),
|
: CupertinoIcons.play_arrow,
|
||||||
if (audio.selectedFilePath != null)
|
color: CupertinoColors.activeBlue,
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.share),
|
|
||||||
onPressed: () {
|
|
||||||
Share.shareFiles([audio.selectedFilePath!]);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
|
onPressed: () {
|
||||||
|
if (audio.isPlaying) {
|
||||||
|
audio.pausePlayback();
|
||||||
|
} else {
|
||||||
|
audio.resumePlayback();
|
||||||
|
}
|
||||||
|
audio.update();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
CupertinoButton(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
child: const Icon(CupertinoIcons.stop,
|
||||||
|
color: CupertinoColors.destructiveRed),
|
||||||
|
onPressed: () {
|
||||||
|
audio.stopPlayback();
|
||||||
|
audio.update();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
CupertinoButton(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
child: const Icon(CupertinoIcons.delete,
|
||||||
|
color: CupertinoColors.destructiveRed),
|
||||||
|
onPressed: () async {
|
||||||
|
showCupertinoModalPopup(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return CupertinoActionSheet(
|
||||||
|
title: Text('Are you sure?'.tr),
|
||||||
|
message: Text(
|
||||||
|
'This will delete all recorded files from your device.'
|
||||||
|
.tr,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
CupertinoActionSheetAction(
|
||||||
|
isDestructiveAction: true,
|
||||||
|
onPressed: () async {
|
||||||
|
await audio.deleteAllRecordedFiles();
|
||||||
|
Navigator.pop(context);
|
||||||
|
audio.update();
|
||||||
|
},
|
||||||
|
child: Text('Delete'.tr),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
cancelButton: CupertinoActionSheetAction(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: Text('Cancel'.tr),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
// File selection and sharing
|
||||||
|
if (audio.selectedFilePath != null)
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
color: CupertinoColors.systemGrey6,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Selected file: ${path.basename(audio.selectedFilePath!)}',
|
||||||
|
style: CupertinoTheme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.textStyle,
|
||||||
|
),
|
||||||
|
CupertinoButton(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
child: const Icon(CupertinoIcons.share),
|
||||||
|
onPressed: () {
|
||||||
|
Share.shareFiles([audio.selectedFilePath!]);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}),
|
})
|
||||||
],
|
],
|
||||||
isleading: true);
|
isleading: true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import 'package:SEFER/views/widgets/my_scafold.dart';
|
|||||||
|
|
||||||
import 'HomePage/about_page.dart';
|
import 'HomePage/about_page.dart';
|
||||||
import 'HomePage/frequentlyQuestionsPage.dart';
|
import 'HomePage/frequentlyQuestionsPage.dart';
|
||||||
|
import 'HomePage/share_app_page.dart';
|
||||||
import 'HomePage/trip_record_page.dart';
|
import 'HomePage/trip_record_page.dart';
|
||||||
import 'profile/passenger_profile_page.dart';
|
import 'profile/passenger_profile_page.dart';
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ class HomePage extends StatelessWidget {
|
|||||||
isleading: true,
|
isleading: true,
|
||||||
title: 'Home Page'.tr,
|
title: 'Home Page'.tr,
|
||||||
body: [
|
body: [
|
||||||
Column(
|
ListView(
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@@ -116,6 +117,19 @@ class HomePage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
onTap: () => Get.to(() => const AboutPage()),
|
onTap: () => Get.to(() => const AboutPage()),
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.share),
|
||||||
|
title: Text(
|
||||||
|
'Share App'.tr,
|
||||||
|
style: AppStyle.headTitle2,
|
||||||
|
),
|
||||||
|
subtitle: Text(
|
||||||
|
'You can share the SEFER App with your friends and earn rewards for rides they take using your code'
|
||||||
|
.tr,
|
||||||
|
style: AppStyle.title,
|
||||||
|
),
|
||||||
|
onTap: () => Get.to(() => ShareAppPage()),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class ApplyOrderWidget extends StatelessWidget {
|
|||||||
right: 0,
|
right: 0,
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: AppStyle.boxDecoration,
|
decoration: AppStyle.boxDecoration,
|
||||||
height: Get.height * .35,
|
height: Get.height * .36,
|
||||||
child: ListView(
|
child: ListView(
|
||||||
children: [
|
children: [
|
||||||
InkWell(
|
InkWell(
|
||||||
@@ -87,11 +87,11 @@ class ApplyOrderWidget extends StatelessWidget {
|
|||||||
width: 10,
|
width: 10,
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
height: Get.height * .3,
|
height: Get.height * .34,
|
||||||
width: Get.width * .9,
|
width: Get.width * .9,
|
||||||
decoration: AppStyle.boxDecoration,
|
decoration: AppStyle.boxDecoration,
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
@@ -241,12 +241,13 @@ class ApplyOrderWidget extends StatelessWidget {
|
|||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
FirebaseMessagesController()
|
FirebaseMessagesController()
|
||||||
.sendNotificationToAnyWithoutData(
|
.sendNotificationToDriverMAP(
|
||||||
'message From passenger',
|
'message From passenger'.tr,
|
||||||
'Hello, I\'m at the agreed-upon location'
|
'Hello, I\'m at the agreed-upon location'
|
||||||
.tr,
|
.tr,
|
||||||
controller.driverToken
|
controller.driverToken
|
||||||
.toString(),
|
.toString(),
|
||||||
|
[],
|
||||||
'ding.wav',
|
'ding.wav',
|
||||||
);
|
);
|
||||||
Get.back();
|
Get.back();
|
||||||
@@ -272,11 +273,12 @@ class ApplyOrderWidget extends StatelessWidget {
|
|||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
FirebaseMessagesController()
|
FirebaseMessagesController()
|
||||||
.sendNotificationToAnyWithoutData(
|
.sendNotificationToDriverMAP(
|
||||||
'message From passenger'.tr,
|
'message From passenger'.tr,
|
||||||
'My location is correct. You can search for me using the navigation app'
|
'My location is correct. You can search for me using the navigation app'
|
||||||
.tr,
|
.tr,
|
||||||
controller.driverToken,
|
controller.driverToken,
|
||||||
|
[],
|
||||||
'ding.wav',
|
'ding.wav',
|
||||||
);
|
);
|
||||||
Get.back();
|
Get.back();
|
||||||
@@ -302,11 +304,12 @@ class ApplyOrderWidget extends StatelessWidget {
|
|||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
FirebaseMessagesController()
|
FirebaseMessagesController()
|
||||||
.sendNotificationToAnyWithoutData(
|
.sendNotificationToDriverMAP(
|
||||||
'message From passenger',
|
'message From passenger',
|
||||||
'My location is correct. You can search for me using the navigation app'
|
'My location is correct. You can search for me using the navigation app'
|
||||||
.tr,
|
.tr,
|
||||||
controller.driverToken,
|
controller.driverToken,
|
||||||
|
[],
|
||||||
'ding.wav',
|
'ding.wav',
|
||||||
);
|
);
|
||||||
Get.back();
|
Get.back();
|
||||||
@@ -331,11 +334,12 @@ class ApplyOrderWidget extends StatelessWidget {
|
|||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
FirebaseMessagesController()
|
FirebaseMessagesController()
|
||||||
.sendNotificationToAnyWithoutData(
|
.sendNotificationToDriverMAP(
|
||||||
'message From passenger',
|
'message From passenger',
|
||||||
"How much longer will you be?"
|
"How much longer will you be?"
|
||||||
.tr,
|
.tr,
|
||||||
controller.driverToken,
|
controller.driverToken,
|
||||||
|
[],
|
||||||
'ding.wav',
|
'ding.wav',
|
||||||
);
|
);
|
||||||
Get.back();
|
Get.back();
|
||||||
@@ -385,13 +389,14 @@ class ApplyOrderWidget extends StatelessWidget {
|
|||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
FirebaseMessagesController()
|
FirebaseMessagesController()
|
||||||
.sendNotificationToAnyWithoutData(
|
.sendNotificationToDriverMAP(
|
||||||
'message From passenger',
|
'message From passenger',
|
||||||
controller
|
controller
|
||||||
.messageToDriver
|
.messageToDriver
|
||||||
.text,
|
.text,
|
||||||
controller
|
controller
|
||||||
.driverToken,
|
.driverToken,
|
||||||
|
[],
|
||||||
'ding.wav');
|
'ding.wav');
|
||||||
controller
|
controller
|
||||||
.messageToDriver
|
.messageToDriver
|
||||||
@@ -466,7 +471,7 @@ class DriverArrivePassengerAndWaitMinute extends StatelessWidget {
|
|||||||
color: controller.remainingTimeDriverWaitPassenger5Minute < 60
|
color: controller.remainingTimeDriverWaitPassenger5Minute < 60
|
||||||
? AppColor.redColor
|
? AppColor.redColor
|
||||||
: AppColor.greenColor,
|
: AppColor.greenColor,
|
||||||
minHeight: 25,
|
minHeight: 15,
|
||||||
borderRadius: BorderRadius.circular(15),
|
borderRadius: BorderRadius.circular(15),
|
||||||
value:
|
value:
|
||||||
controller.progressTimerDriverWaitPassenger5Minute.toDouble(),
|
controller.progressTimerDriverWaitPassenger5Minute.toDouble(),
|
||||||
@@ -513,7 +518,7 @@ class TimeDriverToPassenger extends StatelessWidget {
|
|||||||
Container(
|
Container(
|
||||||
decoration: AppStyle.boxDecoration,
|
decoration: AppStyle.boxDecoration,
|
||||||
width: Get.width * .7,
|
width: Get.width * .7,
|
||||||
height: 35,
|
height: 15,
|
||||||
// color: AppColor.yellowColor,
|
// color: AppColor.yellowColor,
|
||||||
),
|
),
|
||||||
Stack(
|
Stack(
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import 'package:get/get.dart';
|
|||||||
import 'package:SEFER/constant/colors.dart';
|
import 'package:SEFER/constant/colors.dart';
|
||||||
import 'package:SEFER/constant/style.dart';
|
import 'package:SEFER/constant/style.dart';
|
||||||
import 'package:SEFER/controller/home/map_passenger_controller.dart';
|
import 'package:SEFER/controller/home/map_passenger_controller.dart';
|
||||||
|
|
||||||
import '../../widgets/elevated_btn.dart';
|
import '../../widgets/elevated_btn.dart';
|
||||||
|
|
||||||
GetBuilder<MapPassengerController> cancelRidePage() {
|
GetBuilder<MapPassengerController> cancelRidePage() {
|
||||||
Get.put(MapPassengerController());
|
Get.put(MapPassengerController());
|
||||||
|
|
||||||
final List<String> reasons = [
|
final List<String> reasons = [
|
||||||
"I don't need a ride anymore".tr,
|
"I don't need a ride anymore".tr,
|
||||||
"I was just trying the application".tr,
|
"I was just trying the application".tr,
|
||||||
@@ -16,80 +16,74 @@ GetBuilder<MapPassengerController> cancelRidePage() {
|
|||||||
"I don't have a reason".tr,
|
"I don't have a reason".tr,
|
||||||
"Other".tr,
|
"Other".tr,
|
||||||
];
|
];
|
||||||
|
|
||||||
return GetBuilder<MapPassengerController>(
|
return GetBuilder<MapPassengerController>(
|
||||||
builder: (controller) => controller.isCancelRidePageShown
|
builder: (controller) => controller.isCancelRidePageShown
|
||||||
? Positioned(
|
? Positioned(
|
||||||
left: Get.width * .1,
|
left: 20,
|
||||||
top: Get.width * .2,
|
top: Get.height * 0.15,
|
||||||
right: Get.width * .1,
|
right: 20,
|
||||||
bottom: Get.width * .15,
|
bottom: Get.height * 0.15,
|
||||||
child: Container(
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(20),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColor.secondaryColor,
|
color: Colors.white,
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
const BoxShadow(
|
|
||||||
color: AppColor.accentColor,
|
|
||||||
offset: Offset(2, 2),
|
|
||||||
blurRadius: 5),
|
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: AppColor.accentColor.withOpacity(.4),
|
color: Colors.black.withOpacity(0.2),
|
||||||
offset: const Offset(-2, -2),
|
offset: const Offset(0, 8),
|
||||||
blurRadius: 5)
|
blurRadius: 16,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(15)),
|
borderRadius: BorderRadius.circular(20),
|
||||||
),
|
),
|
||||||
height: Get.height * .7,
|
|
||||||
width: Get.width * .7,
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Text(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
'Can we know why you want to cancel Ride ?'.tr,
|
||||||
child: Text(
|
style: AppStyle.title
|
||||||
'Can we know why you want to cancel Ride ?'.tr,
|
.copyWith(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
style: AppStyle.title,
|
textAlign: TextAlign.center,
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(height: 20),
|
||||||
height: 380,
|
Expanded(
|
||||||
width: 300,
|
child: ListView.separated(
|
||||||
child: ListView.builder(
|
|
||||||
itemCount: reasons.length,
|
itemCount: reasons.length,
|
||||||
|
separatorBuilder: (context, index) => const Divider(),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: InkWell(
|
title: Text(
|
||||||
onTap: () {
|
reasons[index],
|
||||||
controller.selectReason(
|
style: AppStyle.title.copyWith(fontSize: 16),
|
||||||
index,
|
),
|
||||||
reasons[index].toString(),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
reasons[index],
|
|
||||||
style: AppStyle.title,
|
|
||||||
)),
|
|
||||||
leading: Radio(
|
leading: Radio(
|
||||||
value: index,
|
value: index,
|
||||||
groupValue: controller.selectedReason,
|
groupValue: controller.selectedReason,
|
||||||
onChanged: (int? value) {
|
onChanged: (int? value) {
|
||||||
controller.selectReason(
|
controller.selectReason(value!, reasons[index]);
|
||||||
value!,
|
|
||||||
reasons[index].toString(),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
activeColor: AppColor.primaryColor,
|
||||||
),
|
),
|
||||||
|
onTap: () {
|
||||||
|
controller.selectReason(index, reasons[index]);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
MyElevatedButton(
|
MyElevatedButton(
|
||||||
title: 'Cancel Ride'.tr,
|
title: 'Cancel Ride'.tr,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (controller.selectedReason == -1) {
|
if (controller.selectedReason == -1) {
|
||||||
Get.snackbar('You Should be select reason.'.tr, '',
|
Get.snackbar(
|
||||||
snackPosition: SnackPosition.BOTTOM,
|
'You Should be select reason.'.tr,
|
||||||
backgroundColor: AppColor.redColor);
|
'',
|
||||||
|
snackPosition: SnackPosition.BOTTOM,
|
||||||
|
backgroundColor: AppColor.redColor,
|
||||||
|
colorText: Colors.white,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
controller.cancelRide();
|
controller.cancelRide();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -586,7 +586,7 @@ class CarDetailsTypeToChoose extends StatelessWidget {
|
|||||||
textToSpeechController,
|
textToSpeechController,
|
||||||
image: 'assets/images/freeRide.png',
|
image: 'assets/images/freeRide.png',
|
||||||
text:
|
text:
|
||||||
'Perfect for adventure seekers who want to experience something new and exciting'
|
"Perfect for passengers seeking the latest car models with the freedom to choose any route they desire"
|
||||||
.tr),
|
.tr),
|
||||||
confirm: MyElevatedButton(
|
confirm: MyElevatedButton(
|
||||||
kolor: AppColor.greenColor,
|
kolor: AppColor.greenColor,
|
||||||
@@ -656,8 +656,10 @@ class CarDetailsTypeToChoose extends StatelessWidget {
|
|||||||
title: 'Next'.tr,
|
title: 'Next'.tr,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.back();
|
Get.back();
|
||||||
if (box.read(BoxName.gender) !=
|
if (box
|
||||||
null) {
|
.read(BoxName.gender)
|
||||||
|
.toString() !=
|
||||||
|
'') {
|
||||||
mapPassengerController
|
mapPassengerController
|
||||||
.isBottomSheetShown = false;
|
.isBottomSheetShown = false;
|
||||||
mapPassengerController.update();
|
mapPassengerController.update();
|
||||||
@@ -710,59 +712,108 @@ class CarDetailsTypeToChoose extends StatelessWidget {
|
|||||||
MainAxisAlignment
|
MainAxisAlignment
|
||||||
.spaceBetween,
|
.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
GestureDetector(
|
||||||
decoration: AppStyle
|
onTap: () {
|
||||||
.boxDecoration1,
|
Get.back();
|
||||||
child: Padding(
|
mapPassengerController
|
||||||
padding:
|
.totalPassenger =
|
||||||
const EdgeInsets
|
mapPassengerController
|
||||||
.all(8.0),
|
.totalPassengerRayehGaiBalash;
|
||||||
child: Column(
|
mapPassengerController
|
||||||
children: [
|
.isBottomSheetShown =
|
||||||
Text('Awfar Car'
|
false;
|
||||||
.tr),
|
mapPassengerController
|
||||||
Text(mapPassengerController
|
.update();
|
||||||
.totalPassengerRayehGaiBalash
|
mapPassengerController
|
||||||
.toStringAsFixed(
|
.changeCashConfirmPageShown();
|
||||||
0)),
|
},
|
||||||
],
|
child: Container(
|
||||||
),
|
decoration: AppStyle
|
||||||
)),
|
.boxDecoration1,
|
||||||
Container(
|
child: Padding(
|
||||||
decoration: AppStyle
|
padding:
|
||||||
.boxDecoration1,
|
const EdgeInsets
|
||||||
child: Padding(
|
.all(8.0),
|
||||||
padding:
|
child: Column(
|
||||||
const EdgeInsets
|
children: [
|
||||||
.all(8.0),
|
Text('Awfar Car'
|
||||||
child: Column(
|
.tr),
|
||||||
children: [
|
Text(mapPassengerController
|
||||||
Text('Speed'.tr),
|
.totalPassengerRayehGaiBalash
|
||||||
Text(mapPassengerController
|
.toStringAsFixed(
|
||||||
.totalPassengerRayehGai
|
0)),
|
||||||
.toStringAsFixed(
|
],
|
||||||
0)),
|
),
|
||||||
],
|
)),
|
||||||
),
|
),
|
||||||
)),
|
GestureDetector(
|
||||||
Container(
|
onTap: () {
|
||||||
decoration: AppStyle
|
Get.back();
|
||||||
.boxDecoration1,
|
mapPassengerController
|
||||||
child: Padding(
|
.totalPassenger =
|
||||||
padding:
|
mapPassengerController
|
||||||
const EdgeInsets
|
.totalPassengerRayehGai;
|
||||||
.all(8.0),
|
mapPassengerController
|
||||||
child: Column(
|
.isBottomSheetShown =
|
||||||
children: [
|
false;
|
||||||
Text(
|
mapPassengerController
|
||||||
'Comfort'.tr),
|
.update();
|
||||||
Text(mapPassengerController
|
mapPassengerController
|
||||||
.totalPassengerRayehGaiComfort
|
.changeCashConfirmPageShown();
|
||||||
.toStringAsFixed(
|
},
|
||||||
0)),
|
child: Container(
|
||||||
],
|
decoration: AppStyle
|
||||||
),
|
.boxDecoration1,
|
||||||
))
|
child: Padding(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets
|
||||||
|
.all(8.0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Speed'.tr),
|
||||||
|
Text(mapPassengerController
|
||||||
|
.totalPassengerRayehGai
|
||||||
|
.toStringAsFixed(
|
||||||
|
0)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Get.back();
|
||||||
|
mapPassengerController
|
||||||
|
.totalPassenger =
|
||||||
|
mapPassengerController
|
||||||
|
.totalPassengerRayehGaiComfort;
|
||||||
|
mapPassengerController
|
||||||
|
.isBottomSheetShown =
|
||||||
|
false;
|
||||||
|
mapPassengerController
|
||||||
|
.update();
|
||||||
|
mapPassengerController
|
||||||
|
.changeCashConfirmPageShown();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
decoration: AppStyle
|
||||||
|
.boxDecoration1,
|
||||||
|
child: Padding(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets
|
||||||
|
.all(8.0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text('Comfort'
|
||||||
|
.tr),
|
||||||
|
Text(mapPassengerController
|
||||||
|
.totalPassengerRayehGaiComfort
|
||||||
|
.toStringAsFixed(
|
||||||
|
0)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
cancel: MyElevatedButton(
|
cancel: MyElevatedButton(
|
||||||
@@ -951,9 +1002,16 @@ class BurcMoney extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HeaderDestination extends StatelessWidget {
|
class HeaderDestination extends StatefulWidget {
|
||||||
const HeaderDestination({super.key});
|
const HeaderDestination({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_HeaderDestinationState createState() => _HeaderDestinationState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HeaderDestinationState extends State<HeaderDestination> {
|
||||||
|
bool _isExpanded = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GetBuilder<MapPassengerController>(
|
return GetBuilder<MapPassengerController>(
|
||||||
@@ -965,95 +1023,64 @@ class HeaderDestination extends StatelessWidget {
|
|||||||
top: Get.height * .08,
|
top: Get.height * .08,
|
||||||
left: 5,
|
left: 5,
|
||||||
right: 5,
|
right: 5,
|
||||||
child: Container(
|
child: GestureDetector(
|
||||||
decoration: AppStyle.boxDecoration1,
|
onTap: () {
|
||||||
height: Get.height * .15,
|
setState(() {
|
||||||
width: Get.width * .8,
|
_isExpanded = !_isExpanded;
|
||||||
child: InkWell(
|
});
|
||||||
onTap: () {
|
},
|
||||||
// mapPassengerController
|
child: AnimatedContainer(
|
||||||
// .getDialog('Are you want to change'.tr, '', () {
|
duration: const Duration(milliseconds: 300),
|
||||||
// Get.back();
|
decoration: AppStyle.boxDecoration1,
|
||||||
// mapPassengerController.cancelRide();
|
height: _isExpanded ? Get.height * .13 : Get.height * .06,
|
||||||
// });
|
width: Get.width * .9,
|
||||||
MyDialog().getDialog(
|
padding: const EdgeInsets.all(8),
|
||||||
"Change Route".tr,
|
|
||||||
'You can change the destination by long-pressing any point on the map'
|
|
||||||
.tr, () {
|
|
||||||
Get.back();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
_isExpanded
|
||||||
padding: const EdgeInsets.symmetric(
|
? Row(
|
||||||
horizontal: 8, vertical: 2),
|
mainAxisAlignment:
|
||||||
child: SizedBox(
|
MainAxisAlignment.spaceBetween,
|
||||||
height: Get.height * .08,
|
children: [
|
||||||
child: ListView(
|
Text('🟢 ', style: AppStyle.subtitle),
|
||||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
Expanded(
|
||||||
//
|
child: Text(
|
||||||
children: [
|
mapPassengerController.startNameAddress,
|
||||||
Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'🟢 ',
|
|
||||||
style: AppStyle.subtitle,
|
style: AppStyle.subtitle,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
SizedBox(
|
),
|
||||||
// height: Get.height * .03,
|
],
|
||||||
width: Get.width * .8,
|
)
|
||||||
child: Text(
|
: const SizedBox(),
|
||||||
mapPassengerController.startNameAddress,
|
Row(
|
||||||
style: AppStyle.subtitle,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
),
|
children: [
|
||||||
),
|
Text('🔴 ', style: AppStyle.subtitle),
|
||||||
],
|
Expanded(
|
||||||
),
|
child: Text(
|
||||||
Row(
|
mapPassengerController.endNameAddress,
|
||||||
mainAxisAlignment:
|
style: AppStyle.subtitle,
|
||||||
MainAxisAlignment.spaceBetween,
|
overflow: TextOverflow.ellipsis,
|
||||||
children: [
|
),
|
||||||
Text(
|
|
||||||
'🔴 ',
|
|
||||||
style: AppStyle.subtitle,
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
// height: Get.height * .03,
|
|
||||||
width: Get.width * .8,
|
|
||||||
child: Text(
|
|
||||||
mapPassengerController.endNameAddress,
|
|
||||||
style: AppStyle.subtitle,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
Padding(
|
if (_isExpanded)
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
Row(
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text('📍', style: AppStyle.subtitle),
|
||||||
'📍 ',
|
Expanded(
|
||||||
style: AppStyle.subtitle,
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: Get.width * .8,
|
|
||||||
child: Text(
|
child: Text(
|
||||||
'${mapPassengerController.distance} ${'KM'.tr} ⌛ ${mapPassengerController.hours > 0 ? '${'Your Ride Duration is '.tr}${mapPassengerController.hours} ${'H and'.tr} ${mapPassengerController.minutes} ${'m'.tr}' : '${'Your Ride Duration is '.tr} ${mapPassengerController.minutes} ${'m'.tr}'}',
|
'${mapPassengerController.distance} ${'KM'.tr} ⌛ ${mapPassengerController.hours > 0 ? '${'Your Ride Duration is '.tr}${mapPassengerController.hours} ${'H and'.tr} ${mapPassengerController.minutes} ${'m'.tr}' : '${'Your Ride Duration is '.tr} ${mapPassengerController.minutes} ${'m'.tr}'}',
|
||||||
style: AppStyle.subtitle,
|
style: AppStyle.subtitle,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ class CashConfirmPageShown extends StatelessWidget {
|
|||||||
? controller.cashConfirmPageShown
|
? controller.cashConfirmPageShown
|
||||||
: 0,
|
: 0,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: box.read(BoxName.carType) == 'Lady'
|
color: box.read(BoxName.carType) == 'Lady' ||
|
||||||
|
box.read(BoxName.carType) == 'Pink Bike'
|
||||||
? Colors.pink.shade100
|
? Colors.pink.shade100
|
||||||
: AppColor.secondaryColor,
|
: AppColor.secondaryColor,
|
||||||
borderRadius: BorderRadius.circular(15)),
|
borderRadius: BorderRadius.circular(15)),
|
||||||
|
|||||||
@@ -419,7 +419,7 @@ class GoogleMapPassengerWidget extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
|
|
||||||
mapType:
|
mapType:
|
||||||
controller.mapType ? MapType.satellite : MapType.normal,
|
controller.mapType ? MapType.satellite : MapType.terrain,
|
||||||
myLocationButtonEnabled: true,
|
myLocationButtonEnabled: true,
|
||||||
// liteModeEnabled: true, tiltGesturesEnabled: false,
|
// liteModeEnabled: true, tiltGesturesEnabled: false,
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:SEFER/views/auth/login_page.dart';
|
||||||
|
import 'package:SEFER/views/auth/sms_verfy_page.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||||
import '../../../constant/colors.dart';
|
import '../../../constant/colors.dart';
|
||||||
|
import '../../../constant/notification.dart';
|
||||||
|
import '../../../controller/firebase/local_notification.dart';
|
||||||
import '../../../controller/functions/tts.dart';
|
import '../../../controller/functions/tts.dart';
|
||||||
import '../../../controller/home/map_passenger_controller.dart';
|
import '../../../controller/home/map_passenger_controller.dart';
|
||||||
|
|
||||||
@@ -89,17 +95,14 @@ GetBuilder<MapPassengerController> leftMainMenuIcons() {
|
|||||||
// borderRadius: BorderRadius.circular(15)),
|
// borderRadius: BorderRadius.circular(15)),
|
||||||
// child: IconButton(
|
// child: IconButton(
|
||||||
// onPressed: () async {
|
// onPressed: () async {
|
||||||
// FirebaseMessagesController().sendNotificationToAnyWithoutData(
|
// final random = Random();
|
||||||
// 'Order'.tr,
|
// final randomMessage =
|
||||||
// 'from: ',
|
// messages[random.nextInt(messages.length)];
|
||||||
// // jsonDecode(value)['message'].toString(),
|
// NotificationController().showNotification(
|
||||||
// 'dEugS-JOT4Ka5riF4s5TEN:APA91bEDL_W7BuEQGbyL-RMaKiMWDlURXhFuaybe5WurTUV8K5eIooSGe22yY22_U2hEZcfPr46ig1v--l00dbOGiivazxvmTyhUyQQW6lJsuIN-wordGtBxtREyeYtEKvxIa1J4ApEu',
|
// randomMessage.split(':')[0],
|
||||||
// 'order.wav'
|
// randomMessage.split(':')[1],
|
||||||
|
// "ding",
|
||||||
// // polylineCoordinates.toString()
|
// );
|
||||||
// );
|
|
||||||
// // print(box.read(BoxName.tokenFCM));
|
|
||||||
// //
|
|
||||||
// },
|
// },
|
||||||
// icon: const Icon(
|
// icon: const Icon(
|
||||||
// Icons.voice_chat,
|
// Icons.voice_chat,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class RideBeginPassenger extends StatelessWidget {
|
|||||||
return Positioned(
|
return Positioned(
|
||||||
left: 10,
|
left: 10,
|
||||||
right: 10,
|
right: 10,
|
||||||
bottom: 4,
|
bottom: 10,
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: AppStyle.boxDecoration,
|
decoration: AppStyle.boxDecoration,
|
||||||
height: controller.statusRide == 'Begin' ? Get.height * .33 : 0,
|
height: controller.statusRide == 'Begin' ? Get.height * .33 : 0,
|
||||||
|
|||||||
@@ -8,6 +8,121 @@ import 'package:SEFER/views/widgets/my_textField.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
import '../../../constant/links.dart';
|
||||||
|
|
||||||
|
// class SearchingCaptainWindow extends StatelessWidget {
|
||||||
|
// const SearchingCaptainWindow({super.key});
|
||||||
|
|
||||||
|
// Widget _buildDriverAvatars(MapPassengerController controller) {
|
||||||
|
// // If no drivers yet, show loading indicator
|
||||||
|
// if (controller.isSearchingWindow) {
|
||||||
|
// // Check if dataCarsLocationByPassenger or its 'data' is null
|
||||||
|
// if (controller.dataCarsLocationByPassenger == null ||
|
||||||
|
// controller.dataCarsLocationByPassenger['data'] == null ||
|
||||||
|
// controller.dataCarsLocationByPassenger['data'].isEmpty) {
|
||||||
|
// return const SizedBox(
|
||||||
|
// height: 60,
|
||||||
|
// child: Center(
|
||||||
|
// child: CircularProgressIndicator(
|
||||||
|
// valueColor:
|
||||||
|
// AlwaysStoppedAnimation<Color>(AppColor.secondaryColor),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return SizedBox(
|
||||||
|
// height: 60,
|
||||||
|
// child: ListView.builder(
|
||||||
|
// scrollDirection: Axis.horizontal,
|
||||||
|
// itemCount: controller.dataCarsLocationByPassenger['data'].length,
|
||||||
|
// padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
// itemBuilder: (context, index) {
|
||||||
|
// final driver = controller.dataCarsLocationByPassenger['data'][index];
|
||||||
|
// return Padding(
|
||||||
|
// padding: const EdgeInsets.only(right: 8),
|
||||||
|
// child: Column(
|
||||||
|
// mainAxisSize: MainAxisSize.min,
|
||||||
|
// children: [
|
||||||
|
// CircleAvatar(
|
||||||
|
// radius: 25,
|
||||||
|
// backgroundColor: AppColor.secondaryColor,
|
||||||
|
// child: ClipOval(
|
||||||
|
// child: Image.network(
|
||||||
|
// '${AppLink.server}/portrate_captain_image/${driver['driver_id']}.jpg',
|
||||||
|
// width: 50,
|
||||||
|
// height: 50,
|
||||||
|
// fit: BoxFit.cover,
|
||||||
|
// errorBuilder: (context, error, stackTrace) {
|
||||||
|
// return const Icon(
|
||||||
|
// Icons.person,
|
||||||
|
// color: Colors.white,
|
||||||
|
// size: 30,
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// Widget build(BuildContext context) {
|
||||||
|
// return GetBuilder<MapPassengerController>(
|
||||||
|
// builder: (mapPassengerController) {
|
||||||
|
// return mapPassengerController.isSearchingWindow
|
||||||
|
// ? Positioned(
|
||||||
|
// bottom: 0,
|
||||||
|
// left: 0,
|
||||||
|
// right: 0,
|
||||||
|
// child: Container(
|
||||||
|
// decoration: AppStyle.boxDecoration1,
|
||||||
|
// height: Get.height *
|
||||||
|
// .3, // Increased height to accommodate avatars
|
||||||
|
// child: Column(
|
||||||
|
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
// children: [
|
||||||
|
// SizedBox(
|
||||||
|
// width: Get.width * .7,
|
||||||
|
// child: const LinearProgressIndicator(
|
||||||
|
// minHeight: 6,
|
||||||
|
// backgroundColor: AppColor.yellowColor,
|
||||||
|
// color: AppColor.secondaryColor,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// mapPassengerController.driverOrderStatus == 'recive'
|
||||||
|
// ? Text(
|
||||||
|
// "Drivers received orders".tr,
|
||||||
|
// style: AppStyle.title,
|
||||||
|
// )
|
||||||
|
// : Text(
|
||||||
|
// "We are searching for the nearest driver to you"
|
||||||
|
// .tr,
|
||||||
|
// style: AppStyle.title,
|
||||||
|
// ),
|
||||||
|
// Text(
|
||||||
|
// 'please wait till driver accept your order'.tr,
|
||||||
|
// style: AppStyle.title,
|
||||||
|
// ),
|
||||||
|
// // New: Driver avatars section
|
||||||
|
// _buildDriverAvatars(mapPassengerController),
|
||||||
|
// _buildTimer(mapPassengerController),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// )
|
||||||
|
// : const SizedBox();
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
class SearchingCaptainWindow extends StatelessWidget {
|
class SearchingCaptainWindow extends StatelessWidget {
|
||||||
const SearchingCaptainWindow({super.key});
|
const SearchingCaptainWindow({super.key});
|
||||||
|
|
||||||
|
|||||||
@@ -116,9 +116,10 @@ class CupertinoDriverListWidget extends StatelessWidget {
|
|||||||
width: 20,
|
width: 20,
|
||||||
height: 20,
|
height: 20,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: hexToColor(
|
color: driver['color_hex'].toString() == 'null'
|
||||||
driver['color_hex'].toString()) ??
|
? Colors.amber
|
||||||
Colors.amber,
|
: hexToColor(
|
||||||
|
driver['color_hex'].toString()),
|
||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
border: Border.all(),
|
border: Border.all(),
|
||||||
),
|
),
|
||||||
@@ -151,9 +152,11 @@ class CupertinoDriverListWidget extends StatelessWidget {
|
|||||||
width: 20,
|
width: 20,
|
||||||
height: 20,
|
height: 20,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: hexToColor(
|
color:
|
||||||
driver['color_hex'].toString()) ??
|
driver['color_hex'].toString() == 'null'
|
||||||
AppColor.bronze,
|
? Colors.amber
|
||||||
|
: hexToColor(
|
||||||
|
driver['color_hex'].toString()),
|
||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
border: Border.all(),
|
border: Border.all(),
|
||||||
),
|
),
|
||||||
@@ -204,7 +207,9 @@ class CupertinoDriverListWidget extends StatelessWidget {
|
|||||||
width: 20,
|
width: 20,
|
||||||
height: 20,
|
height: 20,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: hexToColor(driver['color_hex'].toString()),
|
color: driver['color_hex'].toString() == 'null'
|
||||||
|
? Colors.amber
|
||||||
|
: hexToColor(driver['color_hex'].toString()),
|
||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
border: Border.all(),
|
border: Border.all(),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,64 +1,199 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'dart:convert';
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:SEFER/views/widgets/my_scafold.dart';
|
|
||||||
import 'package:SEFER/views/widgets/mycircular.dart';
|
|
||||||
|
|
||||||
import '../../../controller/home/profile/complaint_controller.dart';
|
import 'package:SEFER/constant/colors.dart';
|
||||||
import '../../widgets/elevated_btn.dart';
|
import 'package:SEFER/constant/style.dart';
|
||||||
|
import 'package:SEFER/controller/functions/crud.dart';
|
||||||
|
import 'package:SEFER/controller/home/profile/complaint_controller.dart';
|
||||||
|
import 'package:SEFER/views/widgets/my_dialog.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import '../../../controller/functions/audio_record1.dart';
|
||||||
|
|
||||||
class ComplaintPage extends StatelessWidget {
|
class ComplaintPage extends StatelessWidget {
|
||||||
// Rename class
|
final ComplaintController complaintController =
|
||||||
ComplaintPage({super.key});
|
Get.put(ComplaintController());
|
||||||
ComplaintController complaintController =
|
final AudioRecorderController audioRecorderController =
|
||||||
Get.put(ComplaintController()); // Update controller instance
|
Get.put(AudioRecorderController());
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MyScafolld(
|
return GetBuilder<ComplaintController>(builder: (complaintController) {
|
||||||
title: 'Complaint'.tr,
|
return CupertinoPageScaffold(
|
||||||
body: [
|
navigationBar: CupertinoNavigationBar(
|
||||||
Padding(
|
middle: Text('Complaint'.tr, style: AppStyle.title),
|
||||||
padding: const EdgeInsets.all(26),
|
|
||||||
child: Form(
|
|
||||||
key: complaintController.formKey,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
TextFormField(
|
|
||||||
controller: complaintController.complaintController,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: const OutlineInputBorder(),
|
|
||||||
hintText: 'Enter your complaint here'.tr,
|
|
||||||
labelText: 'Complaint'.tr, // Update label
|
|
||||||
),
|
|
||||||
validator: (value) {
|
|
||||||
if (value == null || value.isEmpty) {
|
|
||||||
return 'Please enter your complaint.'.tr;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const SizedBox(height: 20),
|
|
||||||
complaintController.isLoading
|
|
||||||
? const MyCircularProgressIndicator()
|
|
||||||
: MyElevatedButton(
|
|
||||||
onPressed: () {
|
|
||||||
if (complaintController.formKey.currentState!
|
|
||||||
.validate()) {
|
|
||||||
complaintController
|
|
||||||
.addComplaint(); // Update method name
|
|
||||||
|
|
||||||
// Clear the complaint form
|
|
||||||
complaintController.formKey.currentState!.reset();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title: 'Submit'.tr,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
child: complaintController.isLoading
|
||||||
isleading: true,
|
? const Center(child: CupertinoActivityIndicator())
|
||||||
);
|
: SafeArea(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Form(
|
||||||
|
key: complaintController.formKey,
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
// Complaint Text Field
|
||||||
|
CupertinoFormSection(
|
||||||
|
header: Text('Submit Your Complaint'.tr),
|
||||||
|
children: [
|
||||||
|
CupertinoTextField(
|
||||||
|
controller:
|
||||||
|
complaintController.complaintController,
|
||||||
|
placeholder: 'Enter your complaint here'.tr,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 12, horizontal: 16),
|
||||||
|
maxLines: 5,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
color: CupertinoColors.systemGrey4),
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
color: CupertinoColors.white,
|
||||||
|
),
|
||||||
|
style: AppStyle.subtitle,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
|
||||||
|
// FutureBuilder to load recorded audio files
|
||||||
|
FutureBuilder<List<String>>(
|
||||||
|
future: audioRecorderController.getRecordedFiles(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.connectionState ==
|
||||||
|
ConnectionState.waiting) {
|
||||||
|
return const Center(
|
||||||
|
child: CupertinoActivityIndicator());
|
||||||
|
} else if (snapshot.hasError) {
|
||||||
|
return Text('Error: ${snapshot.error}',
|
||||||
|
style: AppStyle.subtitle);
|
||||||
|
} else if (snapshot.hasData &&
|
||||||
|
snapshot.data!.isEmpty) {
|
||||||
|
return Text('No audio files recorded.'.tr,
|
||||||
|
style: AppStyle.subtitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// List of recorded audio files
|
||||||
|
return CupertinoFormSection(
|
||||||
|
header: Text('attach audio of complain'.tr),
|
||||||
|
children: snapshot.data!.map((audioFilePath) {
|
||||||
|
final audioFile = File(audioFilePath);
|
||||||
|
return CupertinoListTile(
|
||||||
|
title: Text(audioFilePath.split('/').last,
|
||||||
|
style: AppStyle.title),
|
||||||
|
trailing: const Icon(
|
||||||
|
CupertinoIcons.play_arrow,
|
||||||
|
color: AppColor.accentColor),
|
||||||
|
onTap: () async {
|
||||||
|
MyDialogContent().getDialog(
|
||||||
|
'be sure'.tr,
|
||||||
|
Text('attach correct audio'.tr),
|
||||||
|
() async {
|
||||||
|
await complaintController
|
||||||
|
.uploadAudioFile(audioFile);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
|
||||||
|
// Trip Details Section
|
||||||
|
CupertinoFormSection(
|
||||||
|
header: Text('Trip Details'.tr),
|
||||||
|
children: [
|
||||||
|
CupertinoListTile(
|
||||||
|
title: complaintController.feedBack.isEmpty
|
||||||
|
? Text('No Ride found yet'.tr)
|
||||||
|
: Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'${'Date'.tr}: ${complaintController.feedBack[0]['date']}',
|
||||||
|
style: AppStyle.title),
|
||||||
|
Text(
|
||||||
|
'${'Price'.tr}: ${complaintController.feedBack[0]['price']}',
|
||||||
|
style: AppStyle.title),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
CupertinoFormSection(
|
||||||
|
header: Text('SEFER answer'.tr),
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: 100,
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
// Check if passengerReport is not null
|
||||||
|
if (complaintController.passengerReport !=
|
||||||
|
null)
|
||||||
|
// Access the 'solution' key safely
|
||||||
|
Text(
|
||||||
|
complaintController
|
||||||
|
.passengerReport!['solution']
|
||||||
|
?.toString() ??
|
||||||
|
'No solution available',
|
||||||
|
style: AppStyle.title,
|
||||||
|
)
|
||||||
|
else
|
||||||
|
const SizedBox(), // Fallback if passengerReport is null
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
// Submit Button
|
||||||
|
CupertinoButton(
|
||||||
|
color: AppColor.blueColor,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 14, horizontal: 30),
|
||||||
|
onPressed: () async {
|
||||||
|
if (complaintController.formKey.currentState!
|
||||||
|
.validate()) {
|
||||||
|
if (complaintController.audioLink.toString() ==
|
||||||
|
'') {
|
||||||
|
MyDialogContent().getDialog(
|
||||||
|
'title',
|
||||||
|
Text(
|
||||||
|
'the audio file not uploaded yet \nDo you want to upload without audio file'
|
||||||
|
.tr), () async {
|
||||||
|
await complaintController.geminiAudio(
|
||||||
|
jsonEncode(complaintController.feedBack),
|
||||||
|
complaintController.audioLink,
|
||||||
|
complaintController
|
||||||
|
.complaintController.text);
|
||||||
|
complaintController.formKey.currentState!
|
||||||
|
.reset();
|
||||||
|
});
|
||||||
|
Get.back();
|
||||||
|
} else {
|
||||||
|
await complaintController.geminiAudio(
|
||||||
|
jsonEncode(complaintController.feedBack),
|
||||||
|
complaintController.audioLink,
|
||||||
|
complaintController
|
||||||
|
.complaintController.text);
|
||||||
|
complaintController.formKey.currentState!
|
||||||
|
.reset();
|
||||||
|
}
|
||||||
|
complaintController.addComplaint();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text('Submit'.tr, style: AppStyle.title),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ class MyCircularProgressIndicator extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 110,
|
width: 140,
|
||||||
height: 110,
|
height: 140,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: backgroundColor,
|
color: backgroundColor,
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
@@ -21,13 +21,11 @@ class MyCircularProgressIndicator extends StatelessWidget {
|
|||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
const Center(child: CircularProgressIndicator()),
|
const Center(child: CircularProgressIndicator()),
|
||||||
Column(
|
Image.asset(
|
||||||
children: [
|
'assets/images/logo.gif',
|
||||||
Align(
|
width: 140,
|
||||||
alignment: Alignment.center,
|
height: 140,
|
||||||
child: Image.asset('assets/images/logo.gif'),
|
fit: BoxFit.contain,
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
12
pubspec.lock
12
pubspec.lock
@@ -499,6 +499,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.0"
|
version: "0.3.0"
|
||||||
|
flutter_contacts:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_contacts
|
||||||
|
sha256: "388d32cd33f16640ee169570128c933b45f3259bddbfae7a100bb49e5ffea9ae"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.9+2"
|
||||||
flutter_font_icons:
|
flutter_font_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -974,7 +982,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.2.1"
|
version: "3.2.1"
|
||||||
http_parser:
|
http_parser:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: http_parser
|
name: http_parser
|
||||||
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
|
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
|
||||||
@@ -1270,7 +1278,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "1.15.0"
|
version: "1.15.0"
|
||||||
mime:
|
mime:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: mime
|
name: mime
|
||||||
sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a"
|
sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a"
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ dependencies:
|
|||||||
googleapis_auth: ^1.6.0
|
googleapis_auth: ^1.6.0
|
||||||
flutter_confetti: ^0.3.0
|
flutter_confetti: ^0.3.0
|
||||||
# intl_phone_field: ^3.1.0
|
# intl_phone_field: ^3.1.0
|
||||||
|
flutter_contacts: ^1.1.8
|
||||||
|
mime: ^1.0.6
|
||||||
|
http_parser: ^4.0.2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
BIN
ride9-11.zip
Normal file
BIN
ride9-11.zip
Normal file
Binary file not shown.
Reference in New Issue
Block a user