From 9b0caf3bedb3e5753cac0abf1d51fc748b21e601 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Thu, 10 Oct 2024 16:22:30 +0300 Subject: [PATCH] 10/10/1 --- android/app/build.gradle | 4 +- ios/Runner/Info.plist | 4 +- lib/constant/links.dart | 8 + lib/constant/style.dart | 8 +- .../auth/captin/invit_controller.dart | 158 +++- .../auth/captin/login_captin_controller.dart | 25 + lib/controller/firebase/firbase_messge.dart | 10 +- lib/controller/functions/gemeni.dart | 17 + .../functions/overlay_permisssion.dart | 26 +- .../home/captin/map_driver_controller.dart | 20 + lib/controller/local/translations.dart | 26 + .../ride_available_controller.dart | 2 +- .../payment/payment_controller.dart | 41 +- .../auth/captin/invite_driver_screen.dart | 746 ++++++++++++++---- lib/views/home/Captin/driver_map_page.dart | 19 +- .../Captin/home_captain/drawer_captain.dart | 2 +- .../home/Captin/home_captain/home_captin.dart | 23 +- .../widget/left_menu_map_captain.dart | 54 +- .../google_driver_map_page.dart | 34 +- .../orderCaptin/order_speed_request.dart | 143 ++-- .../notification/available_rides_page.dart | 402 +++------- 21 files changed, 1142 insertions(+), 630 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 1246a23..ef50745 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -54,8 +54,8 @@ android { // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. minSdk = 23 targetSdk = flutter.targetSdkVersion - versionCode = 105 - versionName = '1.5.05' + versionCode = 107 + versionName = '1.5.07' multiDexEnabled =true } diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 17abe8c..597f364 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -33,7 +33,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 64 + 66 CFBundleSignature ???? CFBundleURLTypes @@ -48,7 +48,7 @@ CFBundleVersion - 4.0.64 + 4.0.66 FirebaseAppDelegateProxyEnabled NO GMSApiKey diff --git a/lib/constant/links.dart b/lib/constant/links.dart index 1aa7457..b20b1e4 100644 --- a/lib/constant/links.dart +++ b/lib/constant/links.dart @@ -244,10 +244,18 @@ class AppLink { //===================Auth============ 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"; static String updateInvitationCodeFromRegister = "$server/ride/invitor/updateInvitationCodeFromRegister.php"; + static String updatePassengersInvitation = + "$server/ride/invitor/updatePassengersInvitation.php"; //===================Auth============ diff --git a/lib/constant/style.dart b/lib/constant/style.dart index 9d13b27..b8a4951 100644 --- a/lib/constant/style.dart +++ b/lib/constant/style.dart @@ -7,7 +7,7 @@ import 'colors.dart'; class AppStyle { static TextStyle headTitle = TextStyle( fontWeight: FontWeight.bold, - fontSize: 40, + fontSize: 36, color: AppColor.accentColor, fontFamily: box.read(BoxName.lang) == 'ar' // ?GoogleFonts.notoNaskhArabic().fontFamily @@ -15,21 +15,21 @@ class AppStyle { : GoogleFonts.roboto().fontFamily); static TextStyle headTitle2 = TextStyle( fontWeight: FontWeight.bold, - fontSize: 26, + fontSize: 24, color: AppColor.writeColor, fontFamily: box.read(BoxName.lang) == 'ar' ? GoogleFonts.notoNaskhArabic().fontFamily : GoogleFonts.roboto().fontFamily); static TextStyle title = TextStyle( fontWeight: FontWeight.normal, - fontSize: box.read(BoxName.lang) == 'ar' ? 14 : 16, + fontSize: 14, color: AppColor.writeColor, fontFamily: box.read(BoxName.lang) == 'ar' ? GoogleFonts.notoNaskhArabic().fontFamily : GoogleFonts.roboto().fontFamily); static TextStyle subtitle = TextStyle( fontWeight: FontWeight.bold, - fontSize: 13, + fontSize: 12, color: AppColor.writeColor, fontFamily: box.read(BoxName.lang) == 'ar' ? GoogleFonts.notoNaskhArabic().fontFamily diff --git a/lib/controller/auth/captin/invit_controller.dart b/lib/controller/auth/captin/invit_controller.dart index 96c956a..bae4564 100644 --- a/lib/controller/auth/captin/invit_controller.dart +++ b/lib/controller/auth/captin/invit_controller.dart @@ -10,6 +10,7 @@ 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 '../../../print.dart'; @@ -19,6 +20,42 @@ 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 shareCouponCode() async { + // TODO: Implement sharing functionality + // You can use share_plus package to share the coupon code + } + Future 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 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() { @@ -39,6 +76,20 @@ class InviteController extends GetxController { } catch (e) {} } + void fetchDriverStatsPassengers() async { + try { + var response = await CRUD() + .get(link: AppLink.getDriverInvitationToPassengers, payload: { + "driverId": box.read(BoxName.driverID), + }); + 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; @@ -136,6 +187,57 @@ class InviteController extends GetxController { ); } + void onSelectPassengerInvitation(int index) async { + MyDialog().getDialog( + driverInvitationDataToPassengers[index]['countOfInvitDriver'] < 6 + ? '${'When'.tr} ${driverInvitationDataToPassengers[index]['passengerName']} ${"complete, you can claim your gift".tr} ' + : 'You deserve the gift'.tr, + '${driverInvitationDataToPassengers[index]['passengerName']} ${driverInvitationDataToPassengers[index]['countOfInvitDriver']} / 6 ${'Trip'.tr}', + () async { + if (driverInvitationDataToPassengers[index]['countOfInvitDriver'] < 6) { + 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() + .addDriverWallet('paymentMethod', '50'); + // add for invitor too + await Get.find().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 50".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']; @@ -174,7 +276,7 @@ class InviteController extends GetxController { var response = await CRUD().post(link: AppLink.addInviteDriver, payload: { "driverId": box.read(BoxName.driverID), - "inviterDriverPhone": phoneNumber + "inviterDriverPhone": '+2$phoneNumber' }); if (response != 'failure') { @@ -203,4 +305,58 @@ class InviteController extends GetxController { // Get.snackbar('Error', 'An error occurred'.tr); // } } + + 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.driverID), + "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, + }); } diff --git a/lib/controller/auth/captin/login_captin_controller.dart b/lib/controller/auth/captin/login_captin_controller.dart index 9367d0f..1a08bc4 100644 --- a/lib/controller/auth/captin/login_captin_controller.dart +++ b/lib/controller/auth/captin/login_captin_controller.dart @@ -88,6 +88,31 @@ class LoginDriverController extends GetxController { BoxName.nameDriver, '${jsonDecoeded['data'][0]['first_name']}' ' ${jsonDecoeded['data'][0]['last_name']}'); + if ((jsonDecoeded['data'][0]['model'].toString().contains('دراجه') || + jsonDecoeded['data'][0]['make'].toString().contains('دراجه '))) { + if (jsonDecoeded['data'][0]['gender'].toString() == 'Male') { + box.write(BoxName.carTypeOfDriver, 'Scooter'); + } else { + box.write(BoxName.carTypeOfDriver, 'Pink Bike'); + } + } else if (int.parse(jsonDecoeded['data'][0]['year'].toString()) > + 2017) { + if (jsonDecoeded['data'][0]['gender'].toString() != 'Male') { + box.write(BoxName.carTypeOfDriver, 'Lady'); + } else { + box.write(BoxName.carTypeOfDriver, 'Comfort'); + } + } else if (int.parse(jsonDecoeded['data'][0]['year'].toString()) > + 2002 && + int.parse(jsonDecoeded['data'][0]['year'].toString()) < 2017) { + box.write(BoxName.carTypeOfDriver, 'Speed'); + } else if (int.parse(jsonDecoeded['data'][0]['year'].toString()) < + 2002) { + box.write(BoxName.carTypeOfDriver, 'Awfar Car'); + } + + Log.print( + ' box.write(BoxName.carTypeOfDriver: ${box.read(BoxName.carTypeOfDriver)}'); var token = await CRUD().get( link: AppLink.getDriverToken, diff --git a/lib/controller/firebase/firbase_messge.dart b/lib/controller/firebase/firbase_messge.dart index bcd9342..5f8b809 100644 --- a/lib/controller/firebase/firbase_messge.dart +++ b/lib/controller/firebase/firbase_messge.dart @@ -158,8 +158,16 @@ class FirebaseMessagesController extends GetxController { // Get.to(const VipOrderPage()); } else if (message.notification!.title! == 'message From passenger'.tr) { passengerDialog(message.notification!.body!); + if (Platform.isAndroid) { + NotificationController() + .showNotification('message From passenger'.tr, ''.tr, 'ding', ''); + } } else if (message.notification!.title == 'Cancel') { cancelTripDialog1(); + if (Platform.isAndroid) { + NotificationController() + .showNotification('Cancel'.tr, ''.tr, 'cancel', ''); + } } else if (message.notification!.title! == 'token change') { // NotificationController1() // .showNotification('token change'.tr, 'token change', 'cancel'); @@ -167,7 +175,7 @@ class FirebaseMessagesController extends GetxController { GoogleSignInHelper.signOut(); } else if (message.notification!.title! == 'face detect') { if (Platform.isAndroid) { - NotificationController1() + NotificationController() .showNotification('face detect'.tr, ''.tr, 'tone2', ''); } String result0 = await faceDetector(); diff --git a/lib/controller/functions/gemeni.dart b/lib/controller/functions/gemeni.dart index ae6abd2..25d8966 100644 --- a/lib/controller/functions/gemeni.dart +++ b/lib/controller/functions/gemeni.dart @@ -70,6 +70,23 @@ class AI extends GetxController { } } + Future updatePassengersInvitation() async { + if (formKey.currentState!.validate()) { + var res = await CRUD().post( + link: AppLink.updatePassengersInvitation, + payload: {"inviteCode": invitationCodeController.text}); + if (res != 'failure') { + isInviteDriverFound = true; + update(); + Get.snackbar("Code approved".tr, '', + backgroundColor: AppColor.greenColor); + } else { + Get.snackbar("Code not approved".tr, '', + backgroundColor: AppColor.redColor); + } + } + } + final today = DateTime.now(); Future addDriverAndCarEgypt() async { diff --git a/lib/controller/functions/overlay_permisssion.dart b/lib/controller/functions/overlay_permisssion.dart index 4088f93..5e65557 100644 --- a/lib/controller/functions/overlay_permisssion.dart +++ b/lib/controller/functions/overlay_permisssion.dart @@ -28,25 +28,13 @@ Future getPermissionOverlay() async { } } -// Future getPermissionLocation() async { -// // final PermissionStatus status = await Permission.location.status; -// // if (!status.isGranted) { -// // Log.print('status.isGranted: ${status.isGranted}'); -// // // box.write(BoxName.locationPermission, 'true'); -// // await Permission.location.request(); -// // Get.find().update(); -// // MyDialog().getDialog( -// // 'Enable Location Permission'.tr, // {en:ar} -// // 'Allowing location access will help us display orders near you. Please enable it now.' -// // .tr, // {en:ar} -// // () async { -// // Get.back(); -// // box.write(BoxName.locationPermission, 'true'); -// // await Permission.location.request(); -// // }, -// // ); -// // } -// } +Future closeOverlayIfFound() async { + bool isOverlayActive = await FlutterOverlayWindow.isActive(); + if (isOverlayActive) { + await FlutterOverlayWindow.closeOverlay(); + } +} + final location = Location(); Future getLocationPermission() async { bool serviceEnabled; diff --git a/lib/controller/home/captin/map_driver_controller.dart b/lib/controller/home/captin/map_driver_controller.dart index ca5d50a..b88e588 100644 --- a/lib/controller/home/captin/map_driver_controller.dart +++ b/lib/controller/home/captin/map_driver_controller.dart @@ -462,6 +462,7 @@ class MapDriverController extends GetxController { mapController!.animateCamera( CameraUpdate.newCameraPosition( CameraPosition( + bearing: Get.find().heading, target: myLocation, zoom: 17, // Adjust zoom level as needed ), @@ -527,6 +528,25 @@ class MapDriverController extends GetxController { ? (distanceBetweenDriverAndPassengerWhenConfirm * .08) + (5 * 1) : (distanceBetweenDriverAndPassengerWhenConfirm * .06) + (5 * .06); //for Eygpt other like jordan .06 per minute + await CRUD().post(link: AppLink.updateRides, payload: { + 'id': rideId, + 'rideTimeStart': DateTime.now().toString(), + 'status': 'CancelAfterWait', + }); + CRUD().post( + link: "${AppLink.seferAlexandriaServer}/rides/update.php", + payload: { + 'id': rideId, + 'rideTimeStart': DateTime.now().toString(), + 'status': 'CancelAfterWait', + }); + CRUD() + .post(link: "${AppLink.seferGizaServer}/rides/update.php", payload: { + 'id': rideId, + 'rideTimeStart': DateTime.now().toString(), + 'status': 'CancelAfterWait', + }); + var paymentTokenWait = await generateTokenDriver(costOfWaiting5Minute.toString()); var res = await CRUD().post(link: AppLink.addDrivePayment, payload: { diff --git a/lib/controller/local/translations.dart b/lib/controller/local/translations.dart index adc012a..5df57a0 100644 --- a/lib/controller/local/translations.dart +++ b/lib/controller/local/translations.dart @@ -165,6 +165,32 @@ class MyTranslation extends Translations { 'Rejected Orders Count': "عدد الطلبات المرفوضة", 'This is the total number of rejected orders per day after accepting the orders': 'هذا هو العدد الإجمالي للطلبات المرفوضة يوميًا بعد قبول الطلبات', + "Invite": "دعوة", + "Drivers": "السائقين", + "Passengers": "الركاب", + "Your Driver Referral Code": "رمز الإحالة الخاص بالسائق", + "DRIVER123": "سائق123", + "Share this code with other drivers. Both of you will receive rewards!": + "شارك هذا الرمز مع السائقين الآخرين. سيحصل كل منكما على مكافآت!", + "Share Code": "مشاركة الرمز", + "Invite another driver and both get a gift after he completes 100 trips!": + "ادع سائقًا آخر وسيحصل كلاكما على هدية بعد أن يكمل 100 رحلة!", + "Enter phone": "أدخل رقم الهاتف", + "Send Invite": "إرسال دعوة", + "Show Invitations": "عرض الدعوات", + "No invitation found yet!": "لم يتم العثور على دعوات حتى الآن!", + "Trip": "رحلة", + "Your Passenger Referral Code": "رمز الإحالة الخاص بالراكب", + "SEFER123": "سفر123", + "Share this code with passengers and earn rewards when they use it!": + "شارك هذا الرمز مع الركاب واكسب مكافآت عند استخدامه!", + "Your Rewards": "مكافآتك", + "Total Invites": "إجمالي الدعوات", + "Active Users": "المستخدمون النشطون", + "Total Earnings": "إجمالي الأرباح", + "Choose from contact": "اختر من جهات الاتصال", + "Cancel": "إلغاء", + "No invitation found": "لم يتم العثور على دعوة", 'You are not near the passenger location': "أنت لست بالقرب من موقع الراكب", 'If you need assistance, contact us': diff --git a/lib/controller/notification/ride_available_controller.dart b/lib/controller/notification/ride_available_controller.dart index 37c9b46..1801e3b 100644 --- a/lib/controller/notification/ride_available_controller.dart +++ b/lib/controller/notification/ride_available_controller.dart @@ -44,7 +44,7 @@ class RideAvailableController extends GetxController { var res = await CRUD().get( link: AppLink.getRideWaiting, payload: { - "carType": box.read(BoxName.carTypeOfDriver), + "carType": box.read(BoxName.carTypeOfDriver).toString(), 'southwestLat': bounds.southwest.latitude.toString(), 'southwestLon': bounds.southwest.longitude.toString(), 'northeastLat': bounds.northeast.latitude.toString(), diff --git a/lib/controller/payment/payment_controller.dart b/lib/controller/payment/payment_controller.dart index dcb2451..04a33d2 100644 --- a/lib/controller/payment/payment_controller.dart +++ b/lib/controller/payment/payment_controller.dart @@ -662,25 +662,28 @@ class PaymentController extends GetxController { onPayment: (PaymobResponse response) {}, ); - if (response!.responseCode == 'APPROVED') { - Get.defaultDialog( - barrierDismissible: false, - title: 'Payment Successful'.tr, - titleStyle: AppStyle.title, - // backgroundColor: AppColor.greenColor, - content: Text( - 'The payment was approved.'.tr, - style: AppStyle.title, - ), - confirm: MyElevatedButton( - kolor: AppColor.greenColor, - title: 'OK'.tr, - onPressed: () async { - Get.back(); - method(); - }, - ), - ); + // if (response!.responseCode == 'APPROVED') { + if (response!.responseCode == '200' && response.success == true) { + Toast.show(context, 'Payment Successful'.tr, AppColor.greenColor); + method(); + // Get.defaultDialog( + // barrierDismissible: false, + // title: 'Payment Successful'.tr, + // titleStyle: AppStyle.title, + // // backgroundColor: AppColor.greenColor, + // content: Text( + // 'The payment was approved.'.tr, + // style: AppStyle.title, + // ), + // confirm: MyElevatedButton( + // kolor: AppColor.greenColor, + // title: 'OK'.tr, + // onPressed: () async { + // Get.back(); + // method(); + // }, + // ), + // ); } else { Get.defaultDialog( barrierDismissible: false, diff --git a/lib/views/auth/captin/invite_driver_screen.dart b/lib/views/auth/captin/invite_driver_screen.dart index 8775d63..e108713 100644 --- a/lib/views/auth/captin/invite_driver_screen.dart +++ b/lib/views/auth/captin/invite_driver_screen.dart @@ -1,156 +1,544 @@ import 'package:SEFER/constant/box_name.dart'; import 'package:SEFER/constant/colors.dart'; import 'package:SEFER/main.dart'; +import 'package:SEFER/views/widgets/mydialoug.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; - -import '../../../controller/auth/captin/invit_controller.dart'; import 'package:flutter/cupertino.dart'; import 'package:get/get.dart'; +import '../../../controller/auth/captin/invit_controller.dart'; import '../../widgets/elevated_btn.dart'; -class InviteDriverScreen extends StatelessWidget { +class InviteScreen extends StatelessWidget { final InviteController controller = Get.put(InviteController()); @override Widget build(BuildContext context) { - return CupertinoPageScaffold( - navigationBar: CupertinoNavigationBar( - middle: Text('Invite a Driver'.tr), - leading: CupertinoNavigationBarBackButton( + 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(), ), ), - child: SafeArea( - child: SingleChildScrollView( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Invite another driver and both get a gift after he completes 100 trips!" - .tr, - style: CupertinoTheme.of(context).textTheme.navTitleTextStyle, - ), - const SizedBox(height: 20), - Row( - children: [ - Expanded( - child: CupertinoTextField( - controller: controller.invitePhoneController, - placeholder: 'Enter driver\'s phone'.tr, - keyboardType: TextInputType.phone, + body: SafeArea( + child: GetBuilder( + builder: (controller) { + return Column( + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: Container( + decoration: BoxDecoration( + color: CupertinoColors.systemGrey6, + borderRadius: BorderRadius.circular(8), + ), + child: SegmentedButton( + style: ButtonStyle( + backgroundColor: + MaterialStateProperty.resolveWith( + (states) => states.contains(MaterialState.selected) + ? CupertinoColors.white + : Colors.transparent, + ), + foregroundColor: + MaterialStateProperty.resolveWith( + (states) => states.contains(MaterialState.selected) + ? AppColor.blueColor + : CupertinoColors.label, + ), + ), + segments: [ + ButtonSegment( + value: 0, + label: Padding( + padding: const EdgeInsets.all(8.0), + child: Text('Drivers'.tr), + ), + ), + ButtonSegment( + value: 1, + label: Padding( + padding: const EdgeInsets.all(8.0), + child: Text('Passengers'.tr), + ), + ), + ], + selected: {controller.selectedTab}, + onSelectionChanged: (Set newSelection) { + controller.updateSelectedTab(newSelection.first); + }, ), ), - CupertinoButton( - child: const Icon(CupertinoIcons.person_2), - onPressed: () async { - await controller.pickContacts(); - if (controller.contacts.isNotEmpty) { - if (box.read(BoxName.IsSavedPhones) == null) { - controller.savePhoneToServer(); - box.write(BoxName.IsSavedPhones, true); - } - _showContactsDialog(context); - } - }, + ), + Expanded( + child: SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: controller.selectedTab == 0 + ? _buildDriverTab(context) + : _buildPassengerTab(context), ), - ], - ), - const SizedBox(height: 20), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - MyElevatedButton( - title: 'Send Invite'.tr, - onPressed: controller.sendInvite, - ), - MyElevatedButton( - title: 'Show Invitations'.tr, - onPressed: () async { - controller.fetchDriverStats(); - }, - ), - ], - ), - const SizedBox(height: 20), - GetBuilder( - builder: (controller) { - return SizedBox( - height: Get.height * .4, - child: controller.driverInvitationData.isEmpty - ? Center( - child: Text( - "No invitation found yet!".tr, - style: CupertinoTheme.of(context) - .textTheme - .navTitleTextStyle, - ), - ) - : ListView.builder( - itemCount: controller.driverInvitationData.length, - itemBuilder: (context, index) { - int countOfInvitDriver = int.tryParse(controller - .driverInvitationData[index] - ['countOfInvitDriver'] - ?.toString() ?? - '0') ?? - 0; + ), + ], + ); + }, + ), + ), + ); + } - double progressValue = countOfInvitDriver / 100.0; - progressValue = progressValue.clamp(0.0, 1.0); + Widget _buildDriverTab(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 20), + Text( + "Invite another driver and both get a gift after he completes 100 trips!" + .tr, + style: const TextStyle( + fontSize: 17, + fontWeight: FontWeight.w600, + color: CupertinoColors.label, + ), + ), + const SizedBox(height: 20), + _buildPhoneInput(), + const SizedBox(height: 20), + _buildActionButtons(), + const SizedBox(height: 20), + _buildInvitationsList(context), + ], + ); + } - return GestureDetector( - onTap: () async { - controller.onSelectDriverInvitation(index); - }, - child: Container( - margin: - const EdgeInsets.symmetric(vertical: 8.0), - child: Stack( - alignment: AlignmentDirectional.center, - children: [ - Container( - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(12), - color: CupertinoColors.systemGrey5, - ), - width: Get.width * .85, - height: 35, - child: ClipRRect( - borderRadius: - BorderRadius.circular(12), - child: LinearProgressIndicator( - value: progressValue, - backgroundColor: - CupertinoColors.systemGrey3, - valueColor: - const AlwaysStoppedAnimation< - Color>( - CupertinoColors.activeBlue), - ), - ), - ), - Text( - '${controller.driverInvitationData[index]['invitorName']} ${countOfInvitDriver} / 100 ${'Trip'.tr}', - style: CupertinoTheme.of(context) - .textTheme - .textStyle, - ), - ], - ), - ), - ); - }, - ), - ); - }, - ) + 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 passengers 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 _buildActionButtons() { + 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.sendInvite, + 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.fetchDriverStats(); + }, + ), + ), + ), + ], + ), + ); + } + + 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 _buildInvitationsList(BuildContext context) { + return SizedBox( + height: Get.height * .4, + child: controller.driverInvitationData.isEmpty + ? Center( + child: Text( + "No invitation found yet!".tr, + style: const TextStyle( + color: CupertinoColors.secondaryLabel, + fontSize: 17, + ), + ), + ) + : ListView.builder( + itemCount: controller.driverInvitationData.length, + itemBuilder: (context, index) { + return _buildInvitationItem(context, index); + }, + ), + ); + } + + 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 _buildInvitationItem(BuildContext context, int index) { + int countOfInvitDriver = int.tryParse(controller.driverInvitationData[index] + ['countOfInvitDriver'] + ?.toString() ?? + '0') ?? + 0; + double progressValue = (countOfInvitDriver / 100.0).clamp(0.0, 1.0); + + return GestureDetector( + onTap: () { + controller.onSelectDriverInvitation(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( + controller.driverInvitationData[index]['invitorName'], + 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(AppColor.blueColor), + minHeight: 6, + ), + ), + const SizedBox(height: 4), + Text( + '$countOfInvitDriver / 100 ${'Trip'.tr}', + style: const TextStyle( + fontSize: 13, + color: CupertinoColors.secondaryLabel, + ), + ), + ], + ), + ), + ); + } + + 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(AppColor.blueColor), + minHeight: 6, + ), + ), + const SizedBox(height: 4), + Text( + '$countOfInvitDriver / 6 ${'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, + ), + ), + ], ), ); } @@ -158,34 +546,94 @@ class InviteDriverScreen extends StatelessWidget { void _showContactsDialog(BuildContext context) { showCupertinoModalPopup( context: context, - builder: (BuildContext context) => CupertinoActionSheet( - title: Text('Choose from contact'.tr), - actions: [ - SizedBox( - height: 300, - child: CupertinoScrollbar( + builder: (BuildContext context) => Container( + height: 400, + color: CupertinoColors.systemBackground, + child: Column( + children: [ + Container( + padding: const EdgeInsets.all(16.0), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: CupertinoColors.separator.withOpacity(0.5)), + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + CupertinoButton( + padding: EdgeInsets.zero, + child: Text('Cancel'.tr), + onPressed: () => Navigator.pop(context), + ), + Text( + 'Choose from contact'.tr, + style: const TextStyle( + fontSize: 17, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(width: 60), // For balance + ], + ), + ), + Expanded( child: ListView.builder( itemCount: controller.contactMaps.length, itemBuilder: (context, index) { final contact = controller.contactMaps[index]; - return CupertinoActionSheetAction( - child: Text( - '${contact['name']} - ${controller.formatPhoneNumber(contact['phones'][0].toString())}'), - onPressed: () { - controller.selectPhone(contact['phones'].toString()); - // Navigator.pop(context); - }, + return Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: CupertinoColors.separator.withOpacity(0.5), + ), + ), + ), + child: CupertinoButton( + padding: const EdgeInsets.symmetric( + horizontal: 16, vertical: 12), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + contact['name'], + style: const TextStyle( + color: CupertinoColors.label, + fontSize: 17, + ), + ), + Text( + controller.formatPhoneNumber( + contact['phones'][0].toString()), + style: const TextStyle( + color: CupertinoColors.secondaryLabel, + fontSize: 15, + ), + ), + ], + ), + ), + const Icon( + CupertinoIcons.chevron_right, + color: CupertinoColors.secondaryLabel, + ), + ], + ), + onPressed: () { + controller.selectPhone(contact['phones'].toString()); + // Navigator.pop(context); + }, + ), ); }, ), ), - ), - ], - cancelButton: CupertinoActionSheetAction( - child: Text('Cancel'.tr), - onPressed: () { - Navigator.pop(context); - }, + ], ), ), ); diff --git a/lib/views/home/Captin/driver_map_page.dart b/lib/views/home/Captin/driver_map_page.dart index 949fb3b..fff673e 100644 --- a/lib/views/home/Captin/driver_map_page.dart +++ b/lib/views/home/Captin/driver_map_page.dart @@ -20,18 +20,21 @@ class PassengerLocationMapPage extends StatelessWidget { final LocationController locationController = Get.put(LocationController()); final MapDriverController mapDriverController = Get.put(MapDriverController()); + @override Widget build(BuildContext context) { - if (!mapDriverController.initialized) { - // Call a method to initialize the controller + // if (!mapDriverController.initialized) { + // // Call a method to initialize the controller - mapDriverController.initialized; - } else { - Get.put(MapDriverController()).argumentLoading(); + // mapDriverController.initialized; + // } else { + // Get.put(MapDriverController()).argumentLoading(); - Get.put(MapDriverController()) - .startTimerToShowPassengerInfoWindowFromDriver(); - } + // Get.put(MapDriverController()) + // .startTimerToShowPassengerInfoWindowFromDriver(); + // } + mapDriverController.argumentLoading(); + mapDriverController.startTimerToShowPassengerInfoWindowFromDriver(); return Scaffold( // title: 'Map Passenger'.tr, diff --git a/lib/views/home/Captin/home_captain/drawer_captain.dart b/lib/views/home/Captin/home_captain/drawer_captain.dart index 3a768e3..1ae48cf 100644 --- a/lib/views/home/Captin/home_captain/drawer_captain.dart +++ b/lib/views/home/Captin/home_captain/drawer_captain.dart @@ -78,7 +78,7 @@ class CupertinoDrawerCaptain extends StatelessWidget { _buildDrawerItem( icon: CupertinoIcons.share, text: 'Share App'.tr, - onTap: () => Get.to(() => InviteDriverScreen()), + onTap: () => Get.to(() => InviteScreen()), ), _buildDivider(), _buildDrawerItem( diff --git a/lib/views/home/Captin/home_captain/home_captin.dart b/lib/views/home/Captin/home_captain/home_captin.dart index c989c1d..b6b2c20 100644 --- a/lib/views/home/Captin/home_captain/home_captin.dart +++ b/lib/views/home/Captin/home_captain/home_captin.dart @@ -3,9 +3,9 @@ import 'dart:io'; import 'package:SEFER/constant/box_name.dart'; import 'package:SEFER/controller/home/captin/map_driver_controller.dart'; import 'package:SEFER/views/notification/available_rides_page.dart'; -import 'package:SEFER/views/widgets/mydialoug.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_overlay_window/flutter_overlay_window.dart'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:flutter_font_icons/flutter_font_icons.dart'; @@ -17,7 +17,6 @@ import '../../../../constant/colors.dart'; import '../../../../constant/info.dart'; import '../../../../constant/style.dart'; import '../../../../controller/functions/location_controller.dart'; -import '../../../../controller/functions/location_permission.dart'; import '../../../../controller/functions/overlay_permisssion.dart'; import '../../../../controller/functions/package_info.dart'; import '../../../../controller/home/captin/home_captain_controller.dart'; @@ -38,13 +37,15 @@ class HomeCaptain extends StatelessWidget { @override Widget build(BuildContext context) { Get.put(OrderRequestController()); - Get.put(HomeCaptainController()); + // Get.put(HomeCaptainController()); Get.put(CaptainWalletController()); - WidgetsBinding.instance.addPostFrameCallback((_) { + WidgetsBinding.instance.addPostFrameCallback((_) async { + closeOverlayIfFound(); checkForUpdate(context); getPermissionOverlay(); + // getPermissionLocation1(); - _showFirstTimeOfferNotification(context); + await showFirstTimeOfferNotification(context); }); return Scaffold( appBar: AppBar( @@ -59,16 +60,6 @@ class HomeCaptain extends StatelessWidget { style: AppStyle.title, )), ), - // IconButton( - // // onPressed: () => Get.find().getSQL(), - // onPressed: () => sql.deleteAllData(TableName.driverOrdersRefuse), - // icon: const Icon(Icons.remove)), - // GetBuilder( - // builder: (orderRequestController) => IconButton( - // onPressed: () => - // orderRequestController.getRefusedOrderByCaptain(), - // icon: const Icon(Icons.get_app)), - // ), ], ), drawer: CupertinoDrawerCaptain(), @@ -381,7 +372,7 @@ class HomeCaptain extends StatelessWidget { } } -void _showFirstTimeOfferNotification(BuildContext context) { +showFirstTimeOfferNotification(BuildContext context) async { bool isFirstTime = _checkIfFirstTime(); if (isFirstTime) { diff --git a/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart b/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart index 9da28a8..c54f651 100644 --- a/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart +++ b/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart @@ -185,33 +185,33 @@ GetBuilder leftMainMenuCaptainIcons() { const SizedBox( height: 5, ), - Platform.isAndroid - ? AnimatedContainer( - duration: const Duration(microseconds: 200), - width: controller.widthMapTypeAndTraffic, - decoration: BoxDecoration( - color: AppColor.secondaryColor, - border: Border.all(color: AppColor.blueColor), - borderRadius: BorderRadius.circular(15)), - child: Builder(builder: (context) { - return IconButton( - onPressed: () async { - bool isOverlayActive = - await FlutterOverlayWindow.isActive(); - if (isOverlayActive) { - await FlutterOverlayWindow.closeOverlay(); - } - // print(box.read(BoxName.tokenDriver)); - }, - icon: const Icon( - FontAwesome5.window_close, - size: 29, - color: AppColor.blueColor, - ), - ); - }), - ) - : const SizedBox(), + // Platform.isAndroid + // ? AnimatedContainer( + // duration: const Duration(microseconds: 200), + // width: controller.widthMapTypeAndTraffic, + // decoration: BoxDecoration( + // color: AppColor.secondaryColor, + // border: Border.all(color: AppColor.blueColor), + // borderRadius: BorderRadius.circular(15)), + // child: Builder(builder: (context) { + // return IconButton( + // onPressed: () async { + // bool isOverlayActive = + // await FlutterOverlayWindow.isActive(); + // if (isOverlayActive) { + // await FlutterOverlayWindow.closeOverlay(); + // } + // // print(box.read(BoxName.tokenDriver)); + // }, + // icon: const Icon( + // FontAwesome5.window_close, + // size: 29, + // color: AppColor.blueColor, + // ), + // ); + // }), + // ) + // : const SizedBox(), // AnimatedContainer( // duration: const Duration(microseconds: 200), // width: controller.widthMapTypeAndTraffic, diff --git a/lib/views/home/Captin/mapDriverWidgets/google_driver_map_page.dart b/lib/views/home/Captin/mapDriverWidgets/google_driver_map_page.dart index 56d27eb..e7402de 100644 --- a/lib/views/home/Captin/mapDriverWidgets/google_driver_map_page.dart +++ b/lib/views/home/Captin/mapDriverWidgets/google_driver_map_page.dart @@ -28,39 +28,34 @@ class GoogleDriverMap extends StatelessWidget { onMapCreated: controller.onMapCreated, zoomControlsEnabled: true, initialCameraPosition: CameraPosition( - // bearing: 45, target: locationController.myLocation, zoom: 13, + bearing: locationController.heading, tilt: 40, ), - // onCameraMoveStarted: () {}, - cameraTargetBounds: CameraTargetBounds(controller.boundsData), + cameraTargetBounds: + CameraTargetBounds.unbounded, // Allow unrestricted movement onCameraMove: (position) { locationController.myLocation = position.target; - controller.mapController! - .animateCamera(CameraUpdate.newCameraPosition(position)); + // controller.mapController + // ?.animateCamera(CameraUpdate.newCameraPosition(position)); }, minMaxZoomPreference: const MinMaxZoomPreference(8, 15), - myLocationEnabled: true, myLocationButtonEnabled: true, + myLocationEnabled: true, + myLocationButtonEnabled: true, compassEnabled: true, mapType: MapType.terrain, rotateGesturesEnabled: true, scrollGesturesEnabled: true, trafficEnabled: false, - // liteModeEnabled: true, buildingsEnabled: true, mapToolbarEnabled: true, - // zoomControlsEnabled: true, fortyFiveDegreeImageryEnabled: true, zoomGesturesEnabled: true, polylines: { Polyline( zIndex: 2, - consumeTapEvents: true, geodesic: true, - endCap: Cap.buttCap, - startCap: Cap.buttCap, - visible: true, polylineId: const PolylineId('route1'), points: controller.polylineCoordinates, color: const Color.fromARGB(255, 163, 81, 246), @@ -68,11 +63,7 @@ class GoogleDriverMap extends StatelessWidget { ), Polyline( zIndex: 2, - consumeTapEvents: true, geodesic: true, - endCap: Cap.buttCap, - startCap: Cap.buttCap, - visible: true, polylineId: const PolylineId('route'), points: controller.polylineCoordinatesDestination, color: const Color.fromARGB(255, 10, 29, 126), @@ -81,11 +72,12 @@ class GoogleDriverMap extends StatelessWidget { }, markers: { Marker( - markerId: MarkerId('MyLocation'.tr), - position: locationController.myLocation, - draggable: true, - icon: controller.carIcon, - rotation: locationController.heading), + markerId: MarkerId('MyLocation'.tr), + position: locationController.myLocation, + draggable: true, + icon: controller.carIcon, + rotation: locationController.heading, + ), Marker( markerId: MarkerId('start'.tr), position: controller.latLngPassengerLocation, diff --git a/lib/views/home/Captin/orderCaptin/order_speed_request.dart b/lib/views/home/Captin/orderCaptin/order_speed_request.dart index 22f102c..027bf40 100644 --- a/lib/views/home/Captin/orderCaptin/order_speed_request.dart +++ b/lib/views/home/Captin/orderCaptin/order_speed_request.dart @@ -220,7 +220,7 @@ class OrderSpeedRequest extends StatelessWidget { height: 5, ), Container( - height: Get.height * .15, + height: Get.height * .2, width: Get.width * .9, decoration: AppStyle.boxDecoration1, child: Padding( @@ -301,40 +301,40 @@ class OrderSpeedRequest extends StatelessWidget { ), ), - Padding( - padding: const EdgeInsets.all(4), - child: Container( - color: AppColor.greenColor.withOpacity(.5), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - RichText( - text: TextSpan( - text: 'Cost Of Trip IS '.tr, - style: AppStyle.title, - children: [ - TextSpan( - text: myList[26], style: AppStyle.headTitle2), - ], - ), - ), - RichText( - text: TextSpan( - text: 'Total net'.tr, - style: AppStyle.title, - children: [ - TextSpan( - text: (double.parse(myList[2]) - - double.parse(myList[32])) - .toStringAsFixed(2), - style: AppStyle.headTitle2), - ], - ), - ), - ], - ), - ), - ), + // Padding( + // padding: const EdgeInsets.all(4), + // child: Container( + // color: AppColor.greenColor.withOpacity(.5), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.spaceEvenly, + // children: [ + // RichText( + // text: TextSpan( + // text: 'Cost Of Trip IS '.tr, + // style: AppStyle.title, + // children: [ + // TextSpan( + // text: myList[26], style: AppStyle.headTitle2), + // ], + // ), + // ), + // RichText( + // text: TextSpan( + // text: 'Total net'.tr, + // style: AppStyle.title, + // children: [ + // TextSpan( + // text: (double.parse(myList[2]) - + // double.parse(myList[32])) + // .toStringAsFixed(2), + // style: AppStyle.headTitle2), + // ], + // ), + // ), + // ], + // ), + // ), + // ), Padding( padding: const EdgeInsets.all(8.0), @@ -531,33 +531,52 @@ class OrderSpeedRequest extends StatelessWidget { MyElevatedButton( title: 'Refuse Order'.tr, onPressed: () async { - Get.defaultDialog( - title: 'Reject Order'.tr, - titleStyle: AppStyle.title, - content: Column( - children: [ - IconButton( - onPressed: () async { - await Get.find() - .speakText( - 'You can decline a request without any cost' - .tr); - }, - icon: const Icon(Icons.headphones), - ), - Text( - 'You can decline a request without any cost' - .tr, - style: AppStyle.title, - ) - ], - ), - confirm: MyElevatedButton( - title: 'Ok'.tr, - onPressed: () { - Get.back(); - Get.back(); - })); + // Get.defaultDialog( + // title: 'Reject Order'.tr, + // titleStyle: AppStyle.title, + // content: Column( + // children: [ + // IconButton( + // onPressed: () async { + // await Get.find() + // .speakText( + // 'You can decline a request without any cost' + // .tr); + // }, + // icon: const Icon(Icons.headphones), + // ), + // Text( + // 'You can decline a request without any cost' + // .tr, + // style: AppStyle.title, + // ) + // ], + // ), + // confirm: MyElevatedButton( + // title: 'Ok'.tr, + // onPressed: () { + // Get.back(); + // Get.back(); + // })); + orderRequestController.endTimer(); + + orderRequestController.refuseOrder( + myList[16].toString(), + ); + orderRequestController.addRideToNotificationDriverString( + myList[16].toString(), + myList[29].toString(), + myList[30].toString(), + '${DateTime.now().year}-${DateTime.now().month}-${DateTime.now().day}', + '${DateTime.now().hour}:${DateTime.now().minute}', + myList[2].toString(), + myList[7].toString(), + 'wait', + myList[31].toString(), + myList[33].toString(), + myList[2].toString(), + myList[5].toString(), + myList[4].toString()); }, kolor: AppColor.redColor, ), diff --git a/lib/views/notification/available_rides_page.dart b/lib/views/notification/available_rides_page.dart index 0fe7932..74338d3 100644 --- a/lib/views/notification/available_rides_page.dart +++ b/lib/views/notification/available_rides_page.dart @@ -1,23 +1,11 @@ -import 'dart:convert'; - import 'package:SEFER/constant/colors.dart'; import 'package:SEFER/constant/style.dart'; -import 'package:SEFER/controller/home/captin/home_captain_controller.dart'; import 'package:SEFER/controller/notification/ride_available_controller.dart'; -import 'package:SEFER/views/widgets/elevated_btn.dart'; import 'package:SEFER/views/widgets/my_scafold.dart'; import 'package:SEFER/views/widgets/mycircular.dart'; -import 'package:SEFER/views/widgets/mydialoug.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import '../../constant/box_name.dart'; -import '../../constant/links.dart'; -import '../../controller/firebase/firbase_messge.dart'; -import '../../controller/functions/crud.dart'; -import '../../main.dart'; -import '../home/Captin/driver_map_page.dart'; - class AvailableRidesPage extends StatelessWidget { const AvailableRidesPage({super.key}); @@ -34,293 +22,113 @@ class AvailableRidesPage extends StatelessWidget { : ListView.builder( itemCount: rideAvailableController .rideAvailableMap['message'].length, - itemBuilder: (BuildContext context, int index) { - var list = rideAvailableController - .rideAvailableMap['message'][index]; - return Padding( - padding: const EdgeInsets.all(8.0), - child: Container( - width: Get.width * .9, - decoration: AppStyle.boxDecoration1, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - '🟢 ', - style: AppStyle.subtitle, - ), - SizedBox( - height: Get.height * .06, - width: Get.width * .8, - child: Text( - '${list['startName']}', - style: AppStyle.subtitle, - ), - ), - ], - ), - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - '🔴 ', - style: AppStyle.subtitle, - ), - SizedBox( - height: Get.height * .06, - width: Get.width * .8, - child: Text( - '${list['endName']}', - style: AppStyle.subtitle, - ), - ), - ], - ), - const SizedBox(height: 4), - Row( - mainAxisAlignment: - MainAxisAlignment.spaceAround, - children: [ - Text('${'Price: '.tr}${list['price']} \$'), - const SizedBox(height: 4), - Text( - '${list['carType']}', - style: AppStyle.title - .copyWith(color: AppColor.greenColor), - ), - ], - ), - Row( - mainAxisAlignment: - MainAxisAlignment.spaceAround, - children: [ - Text('📈 ${list['passengerRate']}', - style: AppStyle.title), - MyElevatedButton( - title: 'Accept'.tr, - onPressed: () async { - box.write( - BoxName.statusDriverLocation, 'on'); - - var res = await CRUD().post( - link: AppLink.updateStausFromSpeed, - payload: { - 'id': list['id'], - 'rideTimeStart': - DateTime.now().toString(), - 'status': 'Apply', - 'driver_id': - box.read(BoxName.driverID), - }); - CRUD().post( - link: - '${AppLink.seferAlexandriaServer}rides/updateStausFromSpeed.php', - payload: { - 'id': list['id'], - 'rideTimeStart': - DateTime.now().toString(), - 'status': 'Apply', - 'driver_id': - box.read(BoxName.driverID), - }); - CRUD().post( - link: - '${AppLink.seferGizaServer}rides/updateStausFromSpeed.php', - payload: { - 'id': list['id'], - 'rideTimeStart': - DateTime.now().toString(), - 'status': 'Apply', - 'driver_id': - box.read(BoxName.driverID), - }); - // .then((value) { - // var json = jsonDecode(res); - if (res == "failure") { - MyDialog().getDialog( - "This ride is already taken by another driver." - .tr, - '', () { - CRUD().post( - link: AppLink.deleteAvailableRide, - payload: {'id': list['id']}); - CRUD().post( - link: - '${AppLink.endPoint}/ride/notificationCaptain/deleteAvailableRide.php', - payload: {'id': list['id']}); - Get.back(); - }); - } else if (jsonDecode(res)['status'] == - "success") { - List bodyToPassenger = [ - box.read(BoxName.driverID).toString(), - box - .read(BoxName.nameDriver) - .toString(), - box - .read(BoxName.tokenDriver) - .toString(), - ]; - await CRUD().postFromDialogue( - link: AppLink.addDriverOrder, - payload: { - 'driver_id': - box.read(BoxName.driverID), - // box.read(BoxName.driverID).toString(), - 'order_id': list['id'], - 'status': 'Apply' - }); - CRUD().postFromDialogue( - link: - '${AppLink.seferAlexandriaServer}/driver_order/add.php', - payload: { - 'driver_id': - box.read(BoxName.driverID), - // box.read(BoxName.driverID).toString(), - 'order_id': list['id'], - 'status': 'Apply' - }); - CRUD().postFromDialogue( - link: - '${AppLink.seferGizaServer}/driver_order/add.php', - payload: { - 'driver_id': - box.read(BoxName.driverID), - // box.read(BoxName.driverID).toString(), - 'order_id': list['id'], - 'status': 'Apply' - }); - await CRUD().post( - link: AppLink.updateRides, - payload: { - 'id': list['id'], - 'DriverIsGoingToPassenger': - DateTime.now().toString(), - 'status': 'Applied' - }); - CRUD().post( - link: - '${AppLink.seferAlexandriaServer}/rides/update.php', - payload: { - 'id': list['id'], - 'DriverIsGoingToPassenger': - DateTime.now().toString(), - 'status': 'Applied' - }); - CRUD().post( - link: - '${AppLink.seferGizaServer}/rides/update.php', - payload: { - 'id': list['id'], - 'DriverIsGoingToPassenger': - DateTime.now().toString(), - 'status': 'Applied' - }); - await CRUD().post( - link: AppLink.updateWaitingRide, - payload: { - 'id': list['id'], - 'status': 'Applied' - }); - - FirebaseMessagesController() - .sendNotificationToPassengerToken( - 'Apply Ride', - 'your ride is applied'.tr, - // arguments['DriverList'][9].toString(), - list['passengerToken'] - .toString(), - // box.read(BoxName.tokenDriver).toString(), - bodyToPassenger, - 'start.wav'); - Get.back(); - Get.to(() => PassengerLocationMapPage(), - arguments: { - 'passengerLocation': - list['start_location'] - .toString(), - 'passengerDestination': - list['end_location'] - .toString(), - 'Duration': - list['duration'].toString(), - 'totalCost': - list['price'].toString(), - 'Distance': - list['distance'].toString(), - 'name': - list['first_name'].toString(), - 'phone': list['phone'].toString(), - 'email': list['email'].toString(), - 'WalletChecked': - list['payment_method'] - .toString(), - 'tokenPassenger': - list['passengerToken'] - .toString(), - 'direction': - 'https://www.google.com/maps/dir/${list['start_location']}/${list['end_location']}/', - 'DurationToPassenger': - list['duration'].toString(), - 'rideId': list['id'].toString(), - 'passengerId': - list['passenger_id'] - .toString(), - 'driverId': box - .read(BoxName.driverID) - .toString(), - 'durationOfRideValue': - list['duration'].toString(), - 'paymentAmount': - list['price'].toString(), - 'paymentMethod': - 'cash'.toString() == //todo fix payment method - 'true' - ? 'visa' - : 'cash', - 'isHaveSteps': - 'startEnd'.toString(), - 'step0': ''.toString(), - 'step1': ''.toString(), - 'step2': ''.toString(), - 'step3': ''.toString(), - 'step4': ''.toString(), - 'passengerWalletBurc': - list['bruc'].toString(), - 'timeOfOrder': - DateTime.now().toString(), - 'totalPassenger': - list['price'].toString(), - 'carType': - list['carType'].toString(), - 'kazan': Get.find< - HomeCaptainController>() - .kazan - .toString(), - }); - } - }, - kolor: AppColor.greenColor, - ), - Text( - '📍 ${list['distance']} ${'KM'.tr}', - style: AppStyle.title - .copyWith(color: AppColor.greenColor), - ), - ], - ) - ], - ), - ), - ); - }) + itemBuilder: (context, index) => RideAvailableCard( + rideInfo: rideAvailableController + .rideAvailableMap['message'][index], + ), + ) ], isleading: true); }); } } + +class RideAvailableCard extends StatelessWidget { + final Map rideInfo; + + const RideAvailableCard({Key? key, required this.rideInfo}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Card( + margin: const EdgeInsets.all(8.0), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + elevation: 4, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // _buildLocationRow('🟢', rideInfo['startName']), + // const SizedBox(height: 8), + // _buildLocationRow('🔴', rideInfo['endName']), + _buildLocationRow('↑', rideInfo['startName'], AppColor.greenColor), + const SizedBox(height: 8), + _buildLocationRow('↓', rideInfo['endName'], Colors.red), + const SizedBox(height: 16), + _buildInfoRow(), + const SizedBox(height: 16), + _buildActionRow(), + ], + ), + ), + ); + } + + Widget _buildLocationRow(String icon, String location, Color iconColor) { + return Row( + children: [ + Text( + icon, + style: TextStyle( + fontSize: 20, fontWeight: FontWeight.bold, color: iconColor), + ), + const SizedBox(width: 8), + Expanded( + child: Text( + location, + style: AppStyle.subtitle, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ); + } + + Widget _buildInfoRow() { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('${'Price:'.tr} ${rideInfo['price']} \$', style: AppStyle.title), + Text( + rideInfo['carType'], + style: AppStyle.title.copyWith(color: AppColor.greenColor), + ), + ], + ); + } + + Widget _buildActionRow() { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('📈 ${rideInfo['passengerRate']}', style: AppStyle.title), + const SizedBox(height: 4), + Text( + '📍 ${rideInfo['distance']} ${'KM'.tr}', + style: AppStyle.title.copyWith(color: AppColor.greenColor), + ), + ], + ), + ElevatedButton( + onPressed: () => _acceptRide(), + style: ElevatedButton.styleFrom( + backgroundColor: AppColor.greenColor, + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ), + child: Text('Accept'.tr), + ), + ], + ); + } + + void _acceptRide() async { + // Your existing accept ride logic here + // ... + } +}