From f796f4bc48f81cbff75bc6b27f7dab2666ac13ec Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Sun, 17 Nov 2024 12:02:54 +0200 Subject: [PATCH] 11/17/1 --- android/app/build.gradle | 4 +- ios/Runner/Info.plist | 4 +- .../firebase/local_notification.dart | 152 ++----- lib/controller/functions/crud.dart | 58 ++- .../home/map_passenger_controller.dart | 409 +++++++++--------- .../home/profile/invit_controller.dart | 63 ++- lib/controller/local/local_controller.dart | 77 +--- lib/controller/local/translations.dart | 5 + .../payment/payment_controller.dart | 3 +- lib/main.dart | 29 +- lib/views/home/HomePage/share_app_page.dart | 221 ++++++++-- .../map_widget.dart/left_main_menu_icons.dart | 10 +- lib/views/widgets/mysnakbar.dart | 69 +++ 13 files changed, 611 insertions(+), 493 deletions(-) create mode 100644 lib/views/widgets/mysnakbar.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index 3f33bef..d93fa6f 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -148,8 +148,8 @@ android { // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. minSdk = 23 targetSdk = flutter.targetSdkVersion - versionCode = 94 - versionName = '1.5.94' + versionCode = 97 + versionName = '1.5.97' multiDexEnabled =true // manifestPlaceholders can be specified here if needed diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index ad2e15e..bef9833 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -41,11 +41,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 67 + 69 CFBundleSignature ???? CFBundleVersion - 4.3.67 + 4.3.69 NSHumanReadableCopyright FirebaseAppDelegateProxyEnabled diff --git a/lib/controller/firebase/local_notification.dart b/lib/controller/firebase/local_notification.dart index 0370ab5..e471e04 100644 --- a/lib/controller/firebase/local_notification.dart +++ b/lib/controller/firebase/local_notification.dart @@ -1,92 +1,12 @@ -// 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 initNotifications() async { -// const AndroidInitializationSettings android = -// AndroidInitializationSettings('@mipmap/launcher_icon'); -// const InitializationSettings initializationSettings = -// InitializationSettings(android: android); -// await _flutterLocalNotificationsPlugin.initialize(initializationSettings); -// } - -// // Displays a notification with the given title and message -// void showNotification(String title, String message, String tone) async { -// AndroidNotificationDetails android = AndroidNotificationDetails( -// 'high_importance_channel', -// 'High Importance Notifications', -// importance: Importance.max, -// priority: Priority.high, -// showWhen: false, -// sound: RawResourceAndroidNotificationSound(tone), -// ); -// DarwinNotificationDetails ios = const DarwinNotificationDetails( -// sound: 'default', -// presentAlert: true, -// presentBadge: true, -// presentSound: true, -// ); -// NotificationDetails details = -// NotificationDetails(android: android, iOS: ios); -// await _flutterLocalNotificationsPlugin.show(0, title, message, details); -// } - -// // Schedules a notification after 1 minute -// void scheduleNotificationAfter1Minute( -// String title, String message, String tone) async { -// AndroidNotificationDetails android = AndroidNotificationDetails( -// 'high_importance_channel', 'High Importance Notifications', -// importance: Importance.max, -// priority: Priority.high, -// showWhen: false, -// sound: RawResourceAndroidNotificationSound(tone)); - -// DarwinNotificationDetails ios = const DarwinNotificationDetails( -// sound: 'default', -// presentAlert: true, -// presentBadge: true, -// presentSound: true, -// ); - -// NotificationDetails details = -// NotificationDetails(android: android, iOS: ios); - -// // Schedule the notification to be shown after 1 minute -// final now = tz.TZDateTime.now(tz.local); -// final scheduledTime = now.add(const Duration(minutes: 1)); - -// await _flutterLocalNotificationsPlugin.zonedSchedule( -// 0, -// title, -// message, -// scheduledTime, -// details, -// androidAllowWhileIdle: true, -// uiLocalNotificationDateInterpretation: -// UILocalNotificationDateInterpretation.absoluteTime, -// matchDateTimeComponents: DateTimeComponents.time, -// ); -// } -// } import 'dart:async'; import 'dart:io'; -import 'package:SEFER/constant/box_name.dart'; -import 'package:SEFER/main.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:get/get.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:timezone/data/latest.dart' as tz; import 'package:timezone/timezone.dart' as tz; -import '../../print.dart'; - class NotificationController extends GetxController { final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); @@ -139,8 +59,11 @@ class NotificationController extends GetxController { await _flutterLocalNotificationsPlugin.show(0, title, message, details); print('Notification shown: $title - $message'); } +// /Users/hamzaaleghwairyeen/development/App/ride 2/lib/controller/firebase/local_notification.dart - void scheduleDailyNotifications( +// Assume _flutterLocalNotificationsPlugin is initialized somewhere in your code + + void scheduleNotificationsForSevenDays( String title, String message, String tone) async { final AndroidNotificationDetails android = AndroidNotificationDetails( 'high_importance_channel', @@ -172,53 +95,68 @@ class NotificationController extends GetxController { } } - // 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); + // Schedule notifications for the next 7 days + for (int day = 0; day < 7; day++) { + // Schedule for 8:00 AM + await _scheduleNotificationForTime( + day, 8, 0, title, message, details, day * 1000 + 1); // Unique ID - print('Daily notifications scheduled successfully'); + // Schedule for 3:00 PM + await _scheduleNotificationForTime( + day, 15, 0, title, message, details, day * 1000 + 2); // Unique ID + + // Schedule for 8:00 PM + await _scheduleNotificationForTime( + day, 20, 0, title, message, details, day * 1000 + 3); // Unique ID + } + + print('Notifications scheduled successfully for the next 7 days'); } -// Helper function to get the next instance of a specific hour and minute - Future _scheduleNotificationForTime(int hour, int minute, String title, - String message, NotificationDetails details) async { + Future _scheduleNotificationForTime( + int dayOffset, + int hour, + int minute, + String title, + String message, + NotificationDetails details, + int notificationId, + ) async { // Initialize and set Cairo timezone tz.initializeTimeZones(); - var cairoLocation; - // if (box.read(BoxName.countryCode).toString() == 'Egypt') { - cairoLocation = tz.getLocation('Africa/Cairo'); - // } else { - // cairoLocation = tz.getLocation('UTC'); - // } // todo get for location country - // Set Cairo timezone - Log.print('cairoLocation: ${cairoLocation}'); - final now = tz.TZDateTime.now( - cairoLocation); // Use Cairo timezone for the current time + var cairoLocation = tz.getLocation('Africa/Cairo'); + final now = tz.TZDateTime.now(cairoLocation); tz.TZDateTime scheduledDate = tz.TZDateTime( - cairoLocation, now.year, now.month, now.day, hour, minute); + cairoLocation, + now.year, + now.month, + now.day + dayOffset, // Add offset to schedule for the next days + hour, + minute, + ); - // If scheduled time is already past today, schedule it for the next day + // If the scheduled time is in the past, move it to the next day if (scheduledDate.isBefore(now)) { - scheduledDate = scheduledDate.add(const Duration(days: 1)); + scheduledDate = scheduledDate.add(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 + notificationId, // Unique ID for each notification title, message, scheduledDate, details, - androidAllowWhileIdle: true, + androidScheduleMode: AndroidScheduleMode.exact, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime, - matchDateTimeComponents: DateTimeComponents.time, + matchDateTimeComponents: + null, // Don't repeat automatically; we handle 7 days manually ); - print('Notification scheduled successfully for Cairo timezone'); + + print('Notification scheduled successfully for: $scheduledDate'); } } diff --git a/lib/controller/functions/crud.dart b/lib/controller/functions/crud.dart index 8c0e3a3..96995b0 100644 --- a/lib/controller/functions/crud.dart +++ b/lib/controller/functions/crud.dart @@ -1,18 +1,13 @@ import 'dart:convert'; -import 'dart:io'; -import 'dart:ui'; import 'package:SEFER/constant/box_name.dart'; import 'package:SEFER/constant/links.dart'; import 'package:SEFER/main.dart'; import 'package:get/get.dart'; import 'package:http/http.dart' as http; import 'package:SEFER/env/env.dart'; -import 'package:http_parser/http_parser.dart'; -import 'package:mime/mime.dart'; import '../../constant/api_key.dart'; -import '../../constant/colors.dart'; import '../../print.dart'; import '../../views/widgets/elevated_btn.dart'; import 'add_error.dart'; @@ -79,17 +74,20 @@ class CRUD { } Future sendWhatsAppAuth(String to, String token) async { + var res = await CRUD() + .get(link: AppLink.getApiKey, payload: {'keyName': 'whatsapp_key'}); + var accesstoken = jsonDecode(res)['message']['whatsapp_key']; var headers = { - 'Authorization': 'Bearer ${Env.whatsapp}', + 'Authorization': 'Bearer $accesstoken', 'Content-Type': 'application/json' }; - var request = http.Request( - 'POST', - Uri.parse( - 'https://graph.facebook.com/v20.0/${Env.whatappID}/messages')); - request.body = json.encode({ + + var url = 'https://graph.facebook.com/v20.0/${Env.whatappID}/messages'; + var request = http.Request('POST', Uri.parse(url)); + + var body = json.encode({ "messaging_product": "whatsapp", - "to": to, //"962798583052", + "to": to, "type": "template", "template": { "name": "sefer1", @@ -107,22 +105,38 @@ class CRUD { ] } }); + + request.body = body; request.headers.addAll(headers); - http.StreamedResponse response = await request.send(); + try { + print('Sending request to $url'); + print('Request headers: $headers'); + print('Request body: $body'); - if (response.statusCode == 200) { - print(await response.stream.bytesToString()); - Get.defaultDialog( + http.StreamedResponse response = await request.send(); + + if (response.statusCode == 200) { + String responseBody = await response.stream.bytesToString(); + print('Response: $responseBody'); + + Get.defaultDialog( title: 'You will receive a code in WhatsApp Messenger'.tr, middleText: 'wait 1 minute to recive message'.tr, confirm: MyElevatedButton( - title: 'OK'.tr, - onPressed: () { - Get.back(); - })); - } else { - print(response.reasonPhrase); + title: 'OK'.tr, + onPressed: () { + Get.back(); + }, + ), + ); + } else { + String errorBody = await response.stream.bytesToString(); + print('Error ${response.statusCode}: ${response.reasonPhrase}'); + print('Error body: $errorBody'); + } + } catch (e) { + print('Exception occurred: $e'); } } diff --git a/lib/controller/home/map_passenger_controller.dart b/lib/controller/home/map_passenger_controller.dart index 4664b64..f17c4f5 100644 --- a/lib/controller/home/map_passenger_controller.dart +++ b/lib/controller/home/map_passenger_controller.dart @@ -1,8 +1,11 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:math' show Random, cos, pi, pow, sin, sqrt; +import 'dart:math' show Random, cos, max, min, pi, pow, sin, sqrt; import 'dart:math' as math; +import 'dart:ui'; import 'package:SEFER/constant/univeries_polygon.dart'; +import 'package:SEFER/controller/firebase/local_notification.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter_confetti/flutter_confetti.dart'; import 'package:vector_math/vector_math.dart' show radians, degrees; @@ -1364,7 +1367,7 @@ class MapPassengerController extends GetxController { Set notifiedDrivers = {}; - confirmRideForAllDriverAvailable() async { + confirmRideForAllDriverAvailable11() async { // Fetch car locations await getCarsLocationByPassengerAndReloadMarker( box.read(BoxName.carType), 3000); @@ -1419,7 +1422,7 @@ class MapPassengerController extends GetxController { // Timer for 5 iterations, runs every 2 seconds int iteration = 0; Timer.periodic(const Duration(seconds: 2), (timer) async { - if (iteration >= 5) { + if (iteration >= 10) { timer.cancel(); return; } @@ -1539,94 +1542,117 @@ class MapPassengerController extends GetxController { } } - confirmRideForAllDriverAvailable1() async { - int attempts = 0; - const int maxAttempts = 4; - const Duration delayDuration = Duration(seconds: 2); + Future confirmRideForAllDriverAvailable() async { + // Try to fetch car locations up to 4 times with a 2-second delay + bool driversFound = false; + for (int attempt = 0; attempt < 4; attempt++) { + await getCarsLocationByPassengerAndReloadMarker( + box.read(BoxName.carType), 3000); - // Initial data fetch - await getCarsLocationByPassengerAndReloadMarker( - box.read(BoxName.carType), 3000); - - if (dataCarsLocationByPassenger != null && - dataCarsLocationByPassenger != 'failure') { - PaymentController paymentController = Get.find(); - rideConfirm = true; - shouldFetch = true; - isBottomSheetShown = false; - timeToPassengerFromDriverAfterApplied = 60; - - // Create a set to keep track of notified driver IDs - Set 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()); + // Check if dataCarsLocationByPassenger is valid and contains drivers + if (dataCarsLocationByPassenger != 'failure' && + dataCarsLocationByPassenger != null && + dataCarsLocationByPassenger.containsKey('data') && + dataCarsLocationByPassenger['data'] != null) { + driversFound = true; + break; // Exit loop if drivers are found } - // Periodically check for new drivers - Timer.periodic(delayDuration, (Timer timer) async { - attempts++; + // Wait 2 seconds before next attempt + await Future.delayed(const Duration(seconds: 2)); + } + // If no drivers were found after 4 attempts, show a dialog + if (!driversFound) { + Get.dialog( + BackdropFilter( + filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), + child: CupertinoAlertDialog( + title: Text( + "No Car or Driver Found in your area.".tr, + style: AppStyle.title.copyWith( + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + content: Text( + "No Car or Driver Found in your area.".tr, + style: AppStyle.title.copyWith(fontSize: 16), + ), + actions: [ + CupertinoDialogAction( + onPressed: () { + Get.back(); + Get.offAll(() => const MapPagePassenger()); + }, + child: Text('OK'.tr, + style: const TextStyle(color: AppColor.greenColor)), + ), + ], + ), + ), + barrierDismissible: false, + ); + + return; + } + + // Proceed with the rest of the function if drivers are found + PaymentController paymentController = Get.find(); + 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}'); + } + + // Timer to notify drivers every 2 seconds for 5 iterations + int iteration = 0; + Timer.periodic(const Duration(seconds: 2), (timer) async { + if (iteration >= 5) { + timer.cancel(); + return; + } + iteration++; + + // Reload driver locations and notify available drivers 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 + if (dataCarsLocationByPassenger != null && + dataCarsLocationByPassenger.containsKey('data') && + dataCarsLocationByPassenger['data'] != null) { + for (var driverData in dataCarsLocationByPassenger['data']) { + String driverId = driverData['driver_id'].toString(); + if (!notifiedDrivers.contains(driverId)) { + notifiedDrivers.add(driverId); List body = [ '${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}', '${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}', @@ -1642,10 +1668,11 @@ class MapPassengerController extends GetxController { durationByPassenger.toString(), distanceByPassenger.toString(), paymentController.isWalletChecked.toString(), - driver['token'].toString(), + driverData['token'].toString(), durationToPassenger.toString(), rideId, rideTimerBegin.toString(), + driverId, durationToRide.toString(), Get.find().wayPoints.length > 1 ? 'haveSteps' @@ -1656,10 +1683,10 @@ class MapPassengerController extends GetxController { placesCoordinate[3], placesCoordinate[4], costForDriver.toStringAsFixed(2), - double.parse(box.read(BoxName.passengerWalletTotal)) < 0 + (double.parse(box.read(BoxName.passengerWalletTotal)) < 0 ? double.parse(box.read(BoxName.passengerWalletTotal)) .toStringAsFixed(2) - : '0', + : '0'), box.read(BoxName.email).toString(), data[0]['start_address'], data[0]['end_address'], @@ -1667,37 +1694,43 @@ class MapPassengerController extends GetxController { kazan.toStringAsFixed(0), passengerRate.toStringAsFixed(2), ]; - - // Send notification to the new driver FirebaseMessagesController().sendNotificationToDriverMAP( 'OrderSpeed', - rideId.toString(), - driver['token'].toString(), + rideId, + driverData['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()); + }); + + // If an additional endpoint is available, post data there as well + 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(); } icreaseForSameRideAndDelay() { @@ -1781,7 +1814,7 @@ class MapPassengerController extends GetxController { confirmRideForAllDriverAvailable(); // delayAndFetchRideStatusForAllDriverAvailable(rideId); } else if (rideStatusDelayed == 'Apply' || statusRide == 'Apply') { - Log.print('rideStatusDelayed == Apply: ${rideStatusDelayed}'); + Log.print('rideStatusDelayed == Apply: $rideStatusDelayed'); // todo play sound Get.find() .playSoundFromAssets('assets/start.wav'); @@ -1837,17 +1870,29 @@ class MapPassengerController extends GetxController { int attemptCounter = 0; bool isApplied = false; tick = 0; - Log.print('tick delayAndFetchRideStatusForAllDriverAvailable: $tick'); + bool shouldContinueSearching = true; // Flag to control searching void fetchRideStatus() async { - if (attemptCounter < maxAttempts && isApplied == false || tick < 15) { + if (attemptCounter < maxAttempts && + !isApplied && + shouldContinueSearching) { attemptCounter++; tick++; var res = await getRideStatus(rideId); String rideStatusDelayed = res.toString(); - if (rideStatusDelayed == 'Apply' || rideStatusDelayed == 'Applied') { + if (rideStatusDelayed == 'Cancel') { + shouldContinueSearching = false; // Stop searching + attemptCounter = maxAttempts + 1; + NotificationController().showNotification( + "Order Cancelled".tr, "you canceled order".tr, 'ding'); + } else if (rideStatusDelayed == 'Apply' || + rideStatusDelayed == 'Applied') { await getUpdatedRideForDriverApply(rideId); + NotificationController().showNotification( + 'Order Accepted'.tr, + '$driverName ${'accepted your order at price'.tr} ${totalPassenger.toStringAsFixed(1)} ${'with type'.tr} ${box.read(BoxName.carType)}', + 'ding'); isApplied = true; shouldFetch = false; statusRide = 'Apply'; @@ -1855,89 +1900,14 @@ class MapPassengerController extends GetxController { isSearchingWindow = false; startTimer(); - update(); startTimerFromDriverToPassengerAfterApplied(); + shouldContinueSearching = false; // Stop searching if applied } else if (attemptCounter >= maxAttempts && rideStatusDelayed != 'Cancel') { - shouldFetch = false; - // If the status is still not "Apply" after 15 attempts - MyDialog().getDialog('upgrade price'.tr, - 'You can upgrade price to may driver accept your order'.tr, () { - Get.back(); - Get.defaultDialog( - barrierDismissible: false, - title: "Increase Your Trip Fee (Optional)".tr, - titleStyle: AppStyle.title, - content: Column( - children: [ - Text( - "We haven't found any drivers yet. Consider increasing your trip fee to make your offer more attractive to drivers." - .tr, - style: AppStyle.title, - textAlign: TextAlign.center, - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - IconButton( - onPressed: () { - increasFeeFromPassenger.text = - (totalPassenger + 6).toStringAsFixed(1); - update(); - }, - icon: Column( - children: [ - Text( - '6', - style: AppStyle.number, - ), - Container( - decoration: const BoxDecoration( - shape: BoxShape.circle, - color: AppColor.greenColor), - child: const Icon( - Icons.arrow_circle_up, - size: 30, - color: AppColor.secondaryColor, - ), - ), - ], - ), - ), - SizedBox( - width: 100, - child: Form( - key: increaseFeeFormKey, - child: MyTextForm( - controller: increasFeeFromPassenger, - label: totalPassenger.toStringAsFixed(2), - hint: totalPassenger.toStringAsFixed(2), - type: TextInputType.number), - ), - ), - ], - ) - ], - ), - actions: [ - MyElevatedButton( - title: "No, thanks", - onPressed: () async { - await cancelRide(); - Get.back(); - }), - MyElevatedButton( - title: "Increase Fee".tr, - kolor: AppColor.greenColor, - onPressed: () { - increaseFeeByPassengerAndReOrder(); - }) - ], - ); - }); + shouldContinueSearching = false; // Stop searching + // Show dialog to increase fee... update(); - print('Stopped fetching ride status after 15 attempts.'); } else { Timer(const Duration(seconds: 2), fetchRideStatus); } @@ -2026,7 +1996,7 @@ class MapPassengerController extends GetxController { FirebaseMessagesController().sendNotificationToDriverMAP( 'Order Applied'.tr, '$driverName Apply order\nTake attention in other order'.tr, - driverToken, + driverToken.toString(), [], 'start.wav', ); @@ -2912,7 +2882,7 @@ class MapPassengerController extends GetxController { FirebaseMessagesController().sendNotificationToDriverMAP( 'Cancel Trip'.tr, 'Trip Cancelled'.tr, - driverToken, + driverToken.toString(), [], 'cancel.wav', ); @@ -3313,23 +3283,56 @@ class MapPassengerController extends GetxController { // Log.print('BoxName.serverChosen: ${box.read(BoxName.serverChosen)}'); newStartPointLocation = passengerLocation; - Log.print('passengerLocation: ${passengerLocation}'); + Log.print('passengerLocation: $passengerLocation'); speed = _locationData.speed!; // //print location details isLoading = false; update(); } + // LatLngBounds calculateBounds(double lat, double lng, double radiusInMeters) { + // const double earthRadius = 6378137.0; // Earth's radius in meters + + // double latDelta = radiusInMeters / earthRadius * (180 / pi); + // double lngDelta = + // radiusInMeters / (earthRadius * cos(pi * lat / 180)) * (180 / pi); + + // return LatLngBounds( + // southwest: LatLng(lat - latDelta, lng - lngDelta), + // northeast: LatLng(lat + latDelta, lng + lngDelta), + // ); + // } LatLngBounds calculateBounds(double lat, double lng, double radiusInMeters) { const double earthRadius = 6378137.0; // Earth's radius in meters - double latDelta = radiusInMeters / earthRadius * (180 / pi); + double latDelta = (radiusInMeters / earthRadius) * (180 / pi); double lngDelta = - radiusInMeters / (earthRadius * cos(pi * lat / 180)) * (180 / pi); + (radiusInMeters / (earthRadius * cos(pi * lat / 180))) * (180 / pi); + + double minLat = lat - latDelta; + double maxLat = lat + latDelta; + + double minLng = lng - lngDelta; + double maxLng = lng + lngDelta; + + // Ensure the latitude is between -90 and 90 + minLat = max(-90.0, minLat); + maxLat = min(90.0, maxLat); + + // Ensure the longitude is between -180 and 180 + minLng = (minLng + 180) % 360 - 180; + maxLng = (maxLng + 180) % 360 - 180; + + // Ensure the bounds are in the correct order + if (minLng > maxLng) { + double temp = minLng; + minLng = maxLng; + maxLng = temp; + } return LatLngBounds( - southwest: LatLng(lat - latDelta, lng - lngDelta), - northeast: LatLng(lat + latDelta, lng + lngDelta), + southwest: LatLng(minLat, minLng), + northeast: LatLng(maxLat, maxLng), ); } @@ -3470,7 +3473,7 @@ class MapPassengerController extends GetxController { i < dataCarsLocationByPassenger['message'].length; i++) { var carLocation = dataCarsLocationByPassenger['message'][i]; - Log.print('carLocation: ${carLocation}'); + Log.print('carLocation: $carLocation'); // Calculate distance between passenger's location and current driver's location final distance = Geolocator.distanceBetween( @@ -3482,8 +3485,8 @@ class MapPassengerController extends GetxController { // Calculate duration assuming an average speed of 25 km/h (adjust as needed) int durationToPassenger = (distance * 25 * (1000 / 3600)).round(); - Log.print('distance: ${distance}'); - Log.print('durationToPassenger: ${durationToPassenger}'); + Log.print('distance: $distance'); + Log.print('durationToPassenger: $durationToPassenger'); // Update the UI with the distance and duration for each car update(); @@ -3499,7 +3502,7 @@ class MapPassengerController extends GetxController { latitude: double.parse(carLocation['latitude']), longitude: double.parse(carLocation['longitude']), ); - Log.print('nearestCar: ${nearestCar}'); + Log.print('nearestCar: $nearestCar'); // Update the UI with the nearest driver update(); } @@ -4283,7 +4286,7 @@ class MapPassengerController extends GetxController { totalCostPassenger = totalDriver1 + (totalDriver1 * kazan / 100); totalPassenger = costSpeed + (costSpeed * kazan / 100); if (isInUniversity) { - Log.print('isInUniversity: ${isInUniversity}'); + Log.print('isInUniversity: $isInUniversity'); totalPassengerComfort = 20 + (costComfort + (costComfort * kazan / 100)).ceilToDouble(); totalPassengerLady = @@ -4325,7 +4328,7 @@ class MapPassengerController extends GetxController { totalME = totalCostPassenger - tax; costForDriver = fuelPrice * (20 / 210) * distance; } else { - Log.print('isInUniversity: ${isInUniversity}'); + Log.print('isInUniversity: $isInUniversity'); totalPassengerComfort = (costComfort + (costComfort * kazan / 100)).ceilToDouble(); totalPassengerLady = diff --git a/lib/controller/home/profile/invit_controller.dart b/lib/controller/home/profile/invit_controller.dart index 13e1628..e7307f2 100644 --- a/lib/controller/home/profile/invit_controller.dart +++ b/lib/controller/home/profile/invit_controller.dart @@ -4,8 +4,8 @@ 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:SEFER/views/widgets/mysnakbar.dart'; import 'package:flutter/material.dart'; import 'package:flutter_contacts/contact.dart'; import 'package:flutter_contacts/flutter_contacts.dart'; @@ -13,6 +13,7 @@ import 'package:get/get.dart'; import 'package:share/share.dart'; import '../../../main.dart'; +import '../../../print.dart'; import '../../../views/widgets/my_dialog.dart'; import '../../functions/launch.dart'; import '../../notification/notification_captain_controller.dart'; @@ -117,23 +118,49 @@ Download the SEFER app now and enjoy your ride! Future pickContacts() async { try { + // Request contacts permission if (await FlutterContacts.requestPermission(readonly: true)) { - final List fetchedContacts = - await FlutterContacts.getContacts(withProperties: true); - contacts = fetchedContacts; + // Fetch all contacts with full properties + final List allContacts = await FlutterContacts.getContacts( + withProperties: true, + withThumbnail: false, + withPhoto: true, + ); - // 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(); + // Check if contacts are available + if (allContacts.isNotEmpty) { + // Store the contacts + contacts = allContacts; + Log.print('contacts: $contacts'); - if (contacts.isEmpty) { + // Convert contacts to a list of maps + contactMaps.value = await Future.wait(contacts.map((contact) async { + Log.print('Contact name: ${contact.displayName}'); + + // Fetch phone numbers separately + final phones = await contact.phones; + Log.print('Contact phones: $phones'); + + // Fetch email addresses separately + final emails = await contact.emails; + Log.print('Contact emails: $emails'); + + // Handle empty or null values + return { + 'name': contact.displayName ?? '', + 'phones': phones + .where((phone) => phone.normalizedNumber != null) + .map((phone) => phone.normalizedNumber ?? 'No number') + .toList(), + 'emails': emails + .where((email) => email.address != null) + .map((email) => email.address ?? 'No email') + .toList(), + }; + }).toList()); + + update(); + } else { Get.snackbar('No contacts available'.tr, 'Please add contacts to your phone.'.tr); } @@ -225,8 +252,10 @@ Download the SEFER app now and enjoy your ride! } void sendInviteToPassenger() async { - if (invitePhoneController.text.isEmpty) { - Get.snackbar('Error', 'Please enter an phone address'.tr); + if (invitePhoneController.text.isEmpty || + invitePhoneController.text.length < 11) { + mySnackeBarError('Please enter a correct phone'.tr); + return; } diff --git a/lib/controller/local/local_controller.dart b/lib/controller/local/local_controller.dart index 1f61cb8..ebb51cb 100644 --- a/lib/controller/local/local_controller.dart +++ b/lib/controller/local/local_controller.dart @@ -20,72 +20,58 @@ class LocaleController extends GetxController { case "ar": locale = const Locale("ar"); appTheme = themeArabic; - box.write(BoxName.lang, 'ar'); break; case "en": locale = const Locale("en"); appTheme = themeEnglish; - box.write(BoxName.lang, 'en'); break; case "tr": locale = const Locale("tr"); appTheme = themeEnglish; - box.write(BoxName.lang, 'tr'); break; case "fr": locale = const Locale("fr"); appTheme = themeEnglish; - box.write(BoxName.lang, 'fr'); break; case "it": locale = const Locale("it"); appTheme = themeEnglish; - box.write(BoxName.lang, 'it'); break; case "de": locale = const Locale("de"); appTheme = themeEnglish; - box.write(BoxName.lang, 'de'); break; case "el": locale = const Locale("el"); appTheme = themeEnglish; - box.write(BoxName.lang, 'el'); break; case "es": locale = const Locale("es"); appTheme = themeEnglish; - box.write(BoxName.lang, 'es'); break; case "fa": locale = const Locale("fa"); - appTheme = themeEnglish; - box.write(BoxName.lang, 'fa'); + appTheme = themeArabic; break; case "zh": locale = const Locale("zh"); appTheme = themeEnglish; - box.write(BoxName.lang, 'zh'); break; case "ru": locale = const Locale("ru"); appTheme = themeEnglish; - box.write(BoxName.lang, 'ru'); break; case "hi": locale = const Locale("hi"); appTheme = themeEnglish; - box.write(BoxName.lang, 'hi'); break; default: locale = Locale(Get.deviceLocale!.languageCode); - box.write(BoxName.lang, Get.deviceLocale!.languageCode); appTheme = themeEnglish; break; } box.write(BoxName.lang, langcode); - // box.write(BoxName.lang, langcode); Get.changeTheme(appTheme); Get.updateLocale(locale); restartApp(); @@ -94,62 +80,15 @@ class LocaleController extends GetxController { @override void onInit() { - String storedLang = box.read(BoxName.lang) ?? "ar"; - switch (storedLang) { - case "ar": - language = const Locale("ar"); - appTheme = themeArabic; - break; - case "en": - language = const Locale("en"); - appTheme = themeEnglish; - break; - case "tr": - language = const Locale("tr"); - appTheme = themeEnglish; - break; - case "fr": - language = const Locale("fr"); - appTheme = themeEnglish; - break; - case "it": - language = const Locale("it"); - appTheme = themeEnglish; - break; - case "de": - language = const Locale("de"); - appTheme = themeEnglish; - break; - case "el": - language = const Locale("el"); - appTheme = themeEnglish; - break; - case "es": - language = const Locale("es"); - appTheme = themeEnglish; - break; - case "fa": - language = const Locale("fa"); - appTheme = themeArabic; - break; - case "zh": - language = const Locale("zh"); - appTheme = themeEnglish; - break; - case "ru": - language = const Locale("ru"); - appTheme = themeEnglish; - break; - case "hi": - language = const Locale("hi"); - appTheme = themeEnglish; - break; - default: - language = Locale(Get.deviceLocale!.languageCode); - appTheme = themeEnglish; - break; + String? storedLang = box.read(BoxName.lang); + if (storedLang == null) { + // Use device language if no language is stored + storedLang = Get.deviceLocale!.languageCode; + box.write(BoxName.lang, storedLang); } + changeLang(storedLang); + super.onInit(); } } diff --git a/lib/controller/local/translations.dart b/lib/controller/local/translations.dart index d46e785..2f75fa8 100644 --- a/lib/controller/local/translations.dart +++ b/lib/controller/local/translations.dart @@ -52,13 +52,18 @@ class MyTranslation extends Translations { "Pick or Tap to confirm": "حدد أو انقر للتأكيد", "Select Order Type": "حدد نوع الطلب", "Choose who this order is for": "اختر لمن هذا الطلب", + "Order Accepted": "تم قبول الطلب", "with type": "مع النوع", + "accepted your order at price": "قبل طلبك بالسعر", "I want to order for myself": "أريد أن أطلب لنفسي", "I want to order for someone else": "أريد أن أطلب لشخص آخر", "Cancel Trip from driver": "إلغاء الرحلة من السائق", + "Order Cancelled": "تم إلغاء الطلب", + "you canceled order": "لقد قمت بإلغاء الطلب", "If you want order to another person": "إذا كنت تريد الطلب لشخص آخر", "Ok I will go now.": "حسنًا، سأذهب الآن.", "Hi, I will go now": "مرحبًا، سأذهب الآن.", "upgrade price": "رفع السعر", + 'Please enter a correct phone': 'يرجى إدخال رقم هاتف صحيح', 'airport': 'مطار', "Best choice for a comfortable car with a flexible route and stop points. This airport offers visa entry at this price.": "أفضل اختيار لسيارة مريحة مع طريق ونقاط توقف مرنة. يقدم هذا المطار تأشيرة دخول بهذا السعر.", diff --git a/lib/controller/payment/payment_controller.dart b/lib/controller/payment/payment_controller.dart index b698d24..4aa3bd7 100644 --- a/lib/controller/payment/payment_controller.dart +++ b/lib/controller/payment/payment_controller.dart @@ -699,7 +699,8 @@ class PaymentController extends GetxController { ); // if (response!.success == true && response.responseCode == '200') { - if (response!.responseCode == '200' && response.success == true) { + if (response!.responseCode.toString() == '200' && + response.success == true) { // Log.print('transactionID wewer: ${response.transactionID}'); Toast.show(context, 'Payment Successful'.tr, AppColor.greenColor); method(); diff --git a/lib/main.dart b/lib/main.dart index 4bf3b65..534e1a2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -45,18 +45,6 @@ void main() async { // if (Platform.isAndroid) { 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(); // } @@ -100,13 +88,18 @@ void main() async { userTokenExpiration: 200, iFrameID: 837992, ); - // Get device information - // List> deviceDataList = - // await DeviceInfoPlus.getDeviceInfo(); - // - // // Print all device data - // DeviceInfoPlus.printDeviceInfo(); + 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.scheduleNotificationsForSevenDays( + randomMessage.split(':')[0], + randomMessage.split(':')[1], + "tone1", + ); runApp(const MyApp()); } diff --git a/lib/views/home/HomePage/share_app_page.dart b/lib/views/home/HomePage/share_app_page.dart index 312afca..c5b28d2 100644 --- a/lib/views/home/HomePage/share_app_page.dart +++ b/lib/views/home/HomePage/share_app_page.dart @@ -7,6 +7,7 @@ import '../../../constant/box_name.dart'; import '../../../constant/colors.dart'; import '../../../controller/home/profile/invit_controller.dart'; import '../../../main.dart'; +import '../../../print.dart'; class ShareAppPage extends StatelessWidget { final InviteController controller = Get.put(InviteController()); @@ -81,6 +82,40 @@ class ShareAppPage extends StatelessWidget { ); } + // 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 _buildPhoneInput() { return Container( decoration: BoxDecoration( @@ -102,12 +137,15 @@ class ShareAppPage extends StatelessWidget { color: AppColor.blueColor), onPressed: () async { await controller.pickContacts(); + Log.print('contacts: ${controller.contacts}'); if (controller.contacts.isNotEmpty) { - if (box.read(BoxName.isSavedPhones) == null) { - controller.savePhoneToServer(); - box.write(BoxName.isSavedPhones, true); - } - _showContactsDialog(Get.context!); + _showContactsDialog(Get + .context!); // Show contacts dialog after loading contacts + } else { + Get.snackbar( + 'No contacts available'.tr, + 'Please add contacts to your phone.'.tr, + ); } }, ), @@ -326,48 +364,38 @@ class ShareAppPage extends StatelessWidget { } void _showContactsDialog(BuildContext context) { - showCupertinoModalPopup( - context: context, - builder: (BuildContext context) => Container( + Get.defaultDialog( + title: 'Choose from contact'.tr, + content: SizedBox( 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, - ), - ], - ), + width: 400, 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 - ], - ), - ), + // 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( @@ -433,5 +461,112 @@ class ShareAppPage extends StatelessWidget { ), ), ); + // 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, + // ), + // ], + // ), + // ), + // ); + // }, + // ), + // ), + // ], + // ), + // ), + // ); } } diff --git a/lib/views/home/map_widget.dart/left_main_menu_icons.dart b/lib/views/home/map_widget.dart/left_main_menu_icons.dart index b8f2985..1d9caad 100644 --- a/lib/views/home/map_widget.dart/left_main_menu_icons.dart +++ b/lib/views/home/map_widget.dart/left_main_menu_icons.dart @@ -97,15 +97,7 @@ GetBuilder leftMainMenuIcons() { // borderRadius: BorderRadius.circular(15)), // child: IconButton( // onPressed: () async { - // final random = Random(); - // final randomMessage = - // messages[random.nextInt(messages.length)]; - // NotificationController().showNotification( - // randomMessage.split(':')[0], - // randomMessage.split(':')[1], - // "ding", - // ); - // print(box.read(BoxName.countryCode).toString()); + // Get.to(SmsSignupEgypt()); // }, // icon: const Icon( // Icons.voice_chat, diff --git a/lib/views/widgets/mysnakbar.dart b/lib/views/widgets/mysnakbar.dart new file mode 100644 index 0000000..8b7e73b --- /dev/null +++ b/lib/views/widgets/mysnakbar.dart @@ -0,0 +1,69 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../constant/colors.dart'; + +SnackbarController mySnackeBarError(String message) { + return Get.snackbar( + 'Error'.tr, + message, + backgroundColor: AppColor.redColor.withOpacity(0.9), + colorText: AppColor.secondaryColor, + icon: const Icon(Icons.error, color: AppColor.secondaryColor), + shouldIconPulse: true, + snackPosition: SnackPosition.TOP, + margin: const EdgeInsets.all(10), + borderRadius: 10, + animationDuration: const Duration(milliseconds: 500), + forwardAnimationCurve: Curves.easeOutBack, + reverseAnimationCurve: Curves.easeInBack, + titleText: Text( + 'Error'.tr, + style: const TextStyle( + fontWeight: FontWeight.bold, + color: Colors.white, + fontSize: 16, + ), + ), + messageText: Text( + message, + style: TextStyle( + color: Colors.white.withOpacity(0.9), + fontSize: 14, + ), + ), + ); +} + +SnackbarController mySnackbarSuccess(String message) { + return Get.snackbar( + 'Success'.tr, + message, + backgroundColor: AppColor.greenColor + .withOpacity(0.9), // Assuming green color for success + colorText: AppColor.secondaryColor, + icon: const Icon(Icons.check_circle, color: AppColor.secondaryColor), + shouldIconPulse: true, + snackPosition: SnackPosition.TOP, + margin: const EdgeInsets.all(10), + borderRadius: 10, + animationDuration: const Duration(milliseconds: 500), + forwardAnimationCurve: Curves.easeOutBack, + reverseAnimationCurve: Curves.easeInBack, + titleText: Text( + 'Success'.tr, + style: const TextStyle( + fontWeight: FontWeight.bold, + color: Colors.white, + fontSize: 16, + ), + ), + messageText: Text( + message, + style: TextStyle( + color: Colors.white.withOpacity(0.9), + fontSize: 14, + ), + ), + ); +}