import 'dart:async'; import 'dart:convert'; 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:SEFER/views/widgets/mysnakbar.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_confetti/flutter_confetti.dart'; import 'package:vector_math/vector_math.dart' show radians, degrees; import 'package:SEFER/controller/functions/tts.dart'; import 'package:SEFER/views/home/map_page_passenger.dart'; import 'package:SEFER/views/widgets/my_dialog.dart'; import 'package:SEFER/views/widgets/my_textField.dart'; import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:google_polyline_algorithm/google_polyline_algorithm.dart'; import 'package:intl/intl.dart'; import 'package:location/location.dart'; import 'package:SEFER/constant/colors.dart'; import 'package:SEFER/constant/style.dart'; import 'package:SEFER/controller/home/points_for_rider_controller.dart'; import 'package:SEFER/views/home/map_widget.dart/form_serch_multiy_point.dart'; import '../../constant/api_key.dart'; import '../../constant/box_name.dart'; import '../../constant/info.dart'; import '../../constant/links.dart'; import '../../constant/table_names.dart'; import '../../main.dart'; import '../../models/model/locations.dart'; import '../../models/model/painter_copoun.dart'; import '../../print.dart'; import '../../views/home/map_widget.dart/car_details_widget_to_go.dart'; import '../../views/home/map_widget.dart/select_driver_mishwari.dart'; import '../../views/widgets/elevated_btn.dart'; import '../firebase/firbase_messge.dart'; import '../functions/audio_record1.dart'; import '../functions/crud.dart'; import '../functions/launch.dart'; import '../functions/secure_storage.dart'; import '../payment/payment_controller.dart'; import 'vip_waitting_page.dart'; class MapPassengerController extends GetxController { bool isLoading = true; TextEditingController placeDestinationController = TextEditingController(); TextEditingController increasFeeFromPassenger = TextEditingController(); TextEditingController placeStartController = TextEditingController(); TextEditingController wayPoint0Controller = TextEditingController(); TextEditingController wayPoint1Controller = TextEditingController(); TextEditingController wayPoint2Controller = TextEditingController(); TextEditingController wayPoint3Controller = TextEditingController(); TextEditingController wayPoint4Controller = TextEditingController(); TextEditingController sosPhonePassengerProfile = TextEditingController(); TextEditingController whatsAppLocationText = TextEditingController(); TextEditingController messageToDriver = TextEditingController(); final sosFormKey = GlobalKey(); final promoFormKey = GlobalKey(); final messagesFormKey = GlobalKey(); final increaseFeeFormKey = GlobalKey(); List data = []; List bounds = []; List placesStart = []; List driversToken = []; LatLng previousLocationOfDrivers = const LatLng(0, 0); double angleDegrees = 0; LatLng currentLocationOfDrivers = const LatLng(0, 0); List allTextEditingPlaces = []; List placesDestination = []; List wayPoint0 = []; List wayPoint1 = []; List wayPoint2 = []; List wayPoint3 = []; List wayPoint4 = []; List> placeListResponseAll = []; List placeListResponse = [ formSearchPlaces(0), formSearchPlaces(1), formSearchPlaces(2), formSearchPlaces(3), ]; LatLngBounds? boundsdata; List markers = []; List polyLines = []; late LatLng passengerLocation = const LatLng(32, 34); late LatLng newMyLocation = const LatLng(32.115295, 36.064773); late LatLng newStartPointLocation = const LatLng(32.115295, 36.064773); late LatLng newPointLocation0 = const LatLng(32.115295, 36.064773); late LatLng newPointLocation1 = const LatLng(32.115295, 36.064773); late LatLng newPointLocation2 = const LatLng(32.115295, 36.064773); late LatLng newPointLocation3 = const LatLng(32.115295, 36.064773); late LatLng newPointLocation4 = const LatLng(32.115295, 36.064773); late LatLng myDestination; List polylineCoordinates = []; List polylineCoordinates0 = []; List polylineCoordinates1 = []; List polylineCoordinates2 = []; List polylineCoordinates3 = []; List polylineCoordinates4 = []; List> polylineCoordinatesPointsAll = []; List carsLocationByPassenger = []; List driverCarsLocationToPassengerAfterApplied = []; BitmapDescriptor markerIcon = BitmapDescriptor.defaultMarker; BitmapDescriptor tripIcon = BitmapDescriptor.defaultMarker; BitmapDescriptor startIcon = BitmapDescriptor.defaultMarker; BitmapDescriptor endIcon = BitmapDescriptor.defaultMarker; BitmapDescriptor carIcon = BitmapDescriptor.defaultMarker; BitmapDescriptor motoIcon = BitmapDescriptor.defaultMarker; BitmapDescriptor ladyIcon = BitmapDescriptor.defaultMarker; double height = 150; DateTime currentTime = DateTime.now(); final location = Location(); late LocationData currentLocation; double heightMenu = 0; double widthMenu = 0; double heightPickerContainer = 90; double heightPointsPageForRider = 0; double mainBottomMenuMapHeight = Get.height * .2; double wayPointSheetHeight = 0; String stringRemainingTimeToPassenger = ''; String stringRemainingTimeDriverWaitPassenger5Minute = ''; bool isDriverInPassengerWay = false; bool isDriverArrivePassenger = false; bool startLocationFromMap = false; bool isAnotherOreder = false; bool isWhatsAppOrder = false; bool passengerStartLocationFromMap = false; bool workLocationFromMap = false; bool homeLocationFromMap = false; bool isPassengerRideLocationWidget = false; bool startLocationFromMap0 = false; bool startLocationFromMap1 = false; bool startLocationFromMap2 = false; bool startLocationFromMap3 = false; bool startLocationFromMap4 = false; List startLocationFromMapAll = []; double latePrice = 0; double fuelPrice = 0; double heavyPrice = 0; double naturePrice = 0; bool heightMenuBool = false; String statusRide = 'wait'; String statusRideVip = 'wait'; bool statusRideFromStart = false; bool isPickerShown = false; bool isPointsPageForRider = false; bool isBottomSheetShown = false; bool mapType = false; bool mapTrafficON = false; bool isCancelRidePageShown = false; bool isCashConfirmPageShown = false; bool isPaymentMethodPageShown = false; bool isRideFinished = false; bool rideConfirm = false; bool isMarkersShown = false; bool isMainBottomMenuMap = true; late Timer markerReloadingTimer2; late Timer markerReloadingTimer1; late int durationToPassenger = 0; bool isWayPointSheet = false; bool isWayPointStopsSheet = false; bool isWayPointStopsSheetUtilGetMap = false; double heightBottomSheetShown = 0; double cashConfirmPageShown = 250; late String driverId = ''; late String gender = ''; double widthMapTypeAndTraffic = 50; double paymentPageShown = Get.height * .6; late LatLng southwest; late LatLng northeast; List carLocationsModels = []; var dataCarsLocationByPassenger; var datadriverCarsLocationToPassengerAfterApplied; CarLocation? nearestCar; late Timer markerReloadingTimer; bool shouldFetch = true; // Flag to determine if fetch should be executed int selectedPassengerCount = 1; double progress = 0; double progressTimerToPassengerFromDriverAfterApplied = 0; double progressTimerDriverWaitPassenger5Minute = 0; int durationTimer = 9; int durationToRide = 0; int remainingTime = 25; int remainingTimeToPassengerFromDriverAfterApplied = 60; int remainingTimeDriverWaitPassenger5Minute = 60; int timeToPassengerFromDriverAfterApplied = 0; Timer? timerToPassengerFromDriverAfterApplied; bool rideTimerBegin = false; double progressTimerRideBegin = 0; int remainingTimeTimerRideBegin = 60; String stringRemainingTimeRideBegin = ''; String hintTextStartPoint = 'Search for your Start point'.tr; String hintTextwayPoint0 = 'Search for waypoint'.tr; String hintTextwayPoint1 = 'Search for waypoint'.tr; String hintTextwayPoint2 = 'Search for waypoint'.tr; String hintTextwayPoint3 = 'Search for waypoint'.tr; String hintTextwayPoint4 = 'Search for waypoint'.tr; String currentLocationString = 'Current Location'.tr; String currentLocationString0 = 'Current Location'.tr; String currentLocationString1 = 'Add Location 1'.tr; String currentLocationString2 = 'Add Location 2'.tr; String currentLocationString3 = 'Add Location 3'.tr; String currentLocationString4 = 'Add Location 4'.tr; String placesCoordinate0 = ''.tr; String placesCoordinate1 = ''.tr; String placesCoordinate2 = ''.tr; String placesCoordinate3 = ''.tr; String placesCoordinate4 = ''.tr; List currentLocationStringAll = []; List hintTextwayPointStringAll = []; var placesCoordinate = []; String hintTextDestinationPoint = 'Select your destination'.tr; late String rideId = 'yet'; bool noCarString = false; bool isCashSelectedBeforeConfirmRide = false; bool isPassengerChosen = false; bool isSearchingWindow = false; bool currentLocationToFormPlaces = false; bool currentLocationToFormPlaces0 = false; bool currentLocationToFormPlaces1 = false; bool currentLocationToFormPlaces2 = false; bool currentLocationToFormPlaces3 = false; bool currentLocationToFormPlaces4 = false; List currentLocationToFormPlacesAll = []; late String driverToken = ''; int carsOrder = 0; int wayPointIndex = 0; late double kazan; String? mapAPIKEY; late double totalME = 0; late double tax = 0; late double totalPassenger = 0; late double totalCostPassenger = 0; late double totalPassengerComfort = 0; late double totalPassengerComfortDiscount = 0; late double totalPassengerLadyDiscount = 0; late double totalPassengerSpeedDiscount = 0; late double totalPassengerBalashDiscount = 0; late double totalPassengerRaihGaiDiscount = 0; late double totalPassengerScooter = 0; late double totalDriver = 0; late double averageDuration = 0; late double costDuration = 0; late double costDistance = 0; late double distance = 0; late double duration = 0; late Duration durationToAdd; late DateTime newTime = DateTime.now(); int hours = 0; int minutes = 0; void onChangedPassengerCount(int newValue) { selectedPassengerCount = newValue; update(); } void onChangedPassengersChoose() { isPassengerChosen = true; update(); } void getCurrentLocationFormString() async { currentLocationToFormPlaces = true; currentLocationString = 'Waiting for your location'.tr; await getLocation(); currentLocationString = passengerLocation.toString(); newStartPointLocation = passengerLocation; update(); } List coordinatesWithoutEmpty = []; void getMapPointsForAllMethods() async { clearPolyline(); isMarkersShown = false; isWayPointStopsSheetUtilGetMap = false; isWayPointSheet = false; durationToRide = 0; distanceOfDestination = 0; wayPointSheetHeight = 0; remainingTime = 25; haveSteps = true; // Filter out empty value coordinatesWithoutEmpty = placesCoordinate.where((coord) => coord.isNotEmpty).toList(); latestPosition = LatLng( double.parse(coordinatesWithoutEmpty.last.split(',')[0]), double.parse(coordinatesWithoutEmpty.last.split(',')[1])); for (var i = 0; i < coordinatesWithoutEmpty.length; i++) { if ((i + 1) < coordinatesWithoutEmpty.length) { await getMapPoints( coordinatesWithoutEmpty[i].toString(), coordinatesWithoutEmpty[i + 1].toString(), i, ); if (i == 0) { startNameAddress = data[0]['start_address']; } if (i == coordinatesWithoutEmpty.length) { endNameAddress = data[0]['end_address']; } } } // isWayPointStopsSheet = false; if (haveSteps) { String latestWaypoint = placesCoordinate.lastWhere((coord) => coord.isNotEmpty); latestPosition = LatLng( double.parse(latestWaypoint.split(',')[0]), double.parse(latestWaypoint.split(',')[1]), ); } updateCameraForDistanceAfterGetMap(); changeWayPointStopsSheet(); bottomSheet(); showBottomSheet1(); update(); } void convertHintTextStartNewPlaces(int index) { if (placesStart.isEmpty) { hintTextStartPoint = 'Search for your Start point'.tr; update(); } else { hintTextStartPoint = placesStart[index]['name']; double lat = placesStart[index]['geometry']['location']['lat']; double lng = placesStart[index]['geometry']['location']['lng']; newStartPointLocation = LatLng(lat, lng); update(); } } void convertHintTextPlaces(int index, var res) { if (placeListResponseAll[index].isEmpty) { placeListResponseAll[index] = res; hintTextwayPointStringAll[index] = 'Search for your Start point'.tr; update(); } else { hintTextwayPointStringAll[index] = res['name']; currentLocationStringAll[index] = res['name']; placesCoordinate[index] = '${res['geometry']['location']['lat']},${res['geometry']['location']['lng']}'; placeListResponseAll[index] = []; allTextEditingPlaces[index].clear(); // double lat = wayPoint0[index]['geometry']['location']['lat']; // double lng = wayPoint0[index]['geometry']['location']['lng']; // newPointLocation0 = LatLng(lat, lng); update(); Get.back(); } } increaseFeeByPassengerAndReOrder() async { if (increaseFeeFormKey.currentState!.validate()) { if (double.parse(increasFeeFromPassenger.text) > totalPassenger) { totalPassenger = double.parse(increasFeeFromPassenger.text); Get.back(); if (rideId != 'yet') { await CRUD().post(link: AppLink.updateDriverOrder, payload: { "order_id": rideId.toString(), // Convert to String "status": 'waiting' }); if (AppLink.endPoint != AppLink.seferCairoServer) { CRUD().post( link: "${AppLink.endPoint}/ride/driver_order/update.php", payload: { "order_id": rideId.toString(), // Convert to String "status": 'waiting' }); } await CRUD().post(link: AppLink.updateRides, payload: { "id": rideId.toString(), // Convert to String "status": 'waiting' }); if (AppLink.endPoint != AppLink.seferCairoServer) { CRUD().post( link: "${AppLink.endPoint}/ride/rides/update.php", payload: { "id": rideId.toString(), // Convert to String "status": 'waiting' }); } CRUD().post(link: AppLink.updateWaitingTrip, payload: { "id": rideId.toString(), // Convert to String "status": 'wait' }); if (AppLink.endPoint != AppLink.seferCairoServer) { CRUD().post( link: "${AppLink.endPoint}/ride/notificationCaptain/updateWaitingTrip.php", payload: { "id": rideId.toString(), // Convert to String "status": 'wait' }); } tick = 0; } await getCarsLocationByPassengerAndReloadMarker( box.read(BoxName.carType), 4000); // confirmRideForAllDriverAvailable(); increaseForSameRideAndDelay(); } } } void convertHintTextPlaces1(int index) { if (wayPoint1.isEmpty) { hintTextwayPoint1 = 'Search for your Start point'.tr; update(); } else { hintTextwayPoint1 = wayPoint1[index]['name']; currentLocationString1 = wayPoint1[index]['name']; double lat = wayPoint1[index]['geometry']['location']['lat']; double lng = wayPoint1[index]['geometry']['location']['lng']; newPointLocation1 = LatLng(lat, lng); update(); } } void convertHintTextPlaces2(int index) { if (wayPoint1.isEmpty) { hintTextwayPoint2 = 'Search for your Start point'.tr; update(); } else { hintTextwayPoint2 = wayPoint2[index]['name']; currentLocationString2 = wayPoint1[index]['name']; double lat = wayPoint2[index]['geometry']['location']['lat']; double lng = wayPoint2[index]['geometry']['location']['lng']; newPointLocation2 = LatLng(lat, lng); update(); } } void convertHintTextPlaces3(int index) { if (wayPoint1.isEmpty) { hintTextwayPoint3 = 'Search for your Start point'.tr; update(); } else { hintTextwayPoint3 = wayPoint3[index]['name']; currentLocationString3 = wayPoint1[index]['name']; double lat = wayPoint3[index]['geometry']['location']['lat']; double lng = wayPoint3[index]['geometry']['location']['lng']; newPointLocation3 = LatLng(lat, lng); update(); } } void convertHintTextPlaces4(int index) { if (wayPoint1.isEmpty) { hintTextwayPoint4 = 'Search for your Start point'.tr; update(); } else { hintTextwayPoint4 = wayPoint4[index]['name']; currentLocationString4 = wayPoint1[index]['name']; double lat = wayPoint4[index]['geometry']['location']['lat']; double lng = wayPoint4[index]['geometry']['location']['lng']; newPointLocation4 = LatLng(lat, lng); update(); } } void convertHintTextDestinationNewPlaces(int index) { if (placesDestination.isEmpty) { hintTextDestinationPoint = 'Search for your destination'.tr; update(); } else { hintTextDestinationPoint = placesDestination[index]['title']; // hintTextDestinationPoint = placesDestination[index]['name']; // double lat = placesDestination[index]['geometry']['location']['lat']; double lat = placesDestination[index]['position']['lat']; double lng = placesDestination[index]['position']['lng']; // double lng = placesDestination[index]['geometry']['location']['lng']; newMyLocation = LatLng(lat, lng); update(); } } void convertHintTextDestinationNewPlacesFromRecent( List recentLocations, int index) { hintTextDestinationPoint = recentLocations[index]['name']; double lat = recentLocations[index]['latitude']; double lng = recentLocations[index]['longitude']; newMyLocation = LatLng(lat, lng); update(); } // final mainBottomMenuMap = GlobalKey(); void changeBottomSheetShown() { isBottomSheetShown = !isBottomSheetShown; heightBottomSheetShown = isBottomSheetShown == true ? 250 : 0; update(); } void changeCashConfirmPageShown() { isCashConfirmPageShown = !isCashConfirmPageShown; isCashSelectedBeforeConfirmRide = true; cashConfirmPageShown = isCashConfirmPageShown == true ? 250 : 0; // to get or sure picker point for origin //todo // isPickerShown = true; // clickPointPosition(); update(); } void changePaymentMethodPageShown() { isPaymentMethodPageShown = !isPaymentMethodPageShown; paymentPageShown = isPaymentMethodPageShown == true ? Get.height * .6 : 0; update(); } void changeMapType() { mapType = !mapType; // heightButtomSheetShown = isButtomSheetShown == true ? 240 : 0; update(); } void changeMapTraffic() { mapTrafficON = !mapTrafficON; update(); } void changeisAnotherOreder(bool val) { isAnotherOreder = val; update(); } void changeIsWhatsAppOrder(bool val) { isWhatsAppOrder = val; update(); } void sendSMS(String to) async { // Get the driver's phone number. String driverPhone = dataCarsLocationByPassenger['message'][carsOrder]['phone'].toString(); // Format the message. String message = 'Hi! This is ${box.read(BoxName.name)}.\n I am using ${box.read(AppInformation.appName)} to ride with $passengerName as the driver. $passengerName \nis driving a $model\n with license plate $licensePlate.\n I am currently located at $passengerLocation.\n If you need to reach me, please contact the driver directly at\n\n $driverPhone.'; // Launch the URL to send the SMS. launchCommunication('sms', to, message); } void sendWhatsapp(String to) async { // Get the driver's phone number. // String driverPhone = dataCarsLocationByPassenger['message'][carsOrder]['phone'].toString(); // Format the message. String message = '${'${'Hi! This is'.tr} ${box.read(BoxName.name)}.\n${' I am using'.tr}'} ${AppInformation.appName}${' to ride with'.tr} $passengerName${' as the driver.'.tr} $passengerName \n${'is driving a '.tr}$model\n${' with license plate '.tr}$licensePlate.\n${' I am currently located at '.tr} https://www.google.com/maps/place/${passengerLocation.latitude},${passengerLocation.longitude}.\n${' If you need to reach me, please contact the driver directly at'.tr}\n\n $driverPhone.'; // Launch the URL to send the WhatsApp message. launchCommunication('whatsapp', to, message); } void changeCancelRidePageShow() { // rideConfirm == true // ? isCancelRidePageShown = !isCancelRidePageShown; // : cancelRide(); update(); } void getDrawerMenu() { heightMenuBool = !heightMenuBool; widthMapTypeAndTraffic = heightMenuBool == true ? 0 : 50; heightMenu = heightMenuBool == true ? 70 : 0; widthMenu = heightMenuBool == true ? 110 : 0; update(); } calcualateDistsanceInMetet(LatLng prev, current) async { double distance2 = Geolocator.distanceBetween( prev.latitude, prev.longitude, current.latitude, current.longitude, ); return distance2; } // bool isTimerFromDriverToPassengerAfterAppliedRunning = true; // int beginRideInterval = 4; // Interval in seconds for getBeginRideFromDriver // void startTimerFromDriverToPassengerAfterApplied() async { // int secondsElapsed = 0; // while (secondsElapsed <= timeToPassengerFromDriverAfterApplied && // isTimerFromDriverToPassengerAfterAppliedRunning) { // await Future.delayed(const Duration(seconds: 1)); // secondsElapsed++; // progressTimerToPassengerFromDriverAfterApplied = // secondsElapsed / timeToPassengerFromDriverAfterApplied; // remainingTimeToPassengerFromDriverAfterApplied = // timeToPassengerFromDriverAfterApplied - secondsElapsed; // if (remainingTimeToPassengerFromDriverAfterApplied < 59) { // if (rideTimerBegin == false) { // rideTimerBegin = true; // } // } // // Call getBeginRideFromDriver every 4 seconds // if (secondsElapsed % beginRideInterval == 0) { // getBeginRideFromDriver(); // uploadPassengerLocation(); // } // int minutes = // (remainingTimeToPassengerFromDriverAfterApplied / 60).floor(); // int seconds = remainingTimeToPassengerFromDriverAfterApplied % 60; // stringRemainingTimeToPassenger = // '$minutes:${seconds.toString().padLeft(2, '0')}'; // update(); // } // } StreamController _timerStreamController = StreamController(); Stream get timerStream => _timerStreamController.stream; bool isTimerFromDriverToPassengerAfterAppliedRunning = true; bool isTimerRunning = false; // Flag to track if the timer is running int beginRideInterval = 4; // Interval in seconds for getBeginRideFromDriver void startTimerFromDriverToPassengerAfterApplied() { if (isTimerRunning) return; // Prevent duplicate streams isTimerRunning = true; int secondsElapsed = 0; // Start the stream Timer.periodic(const Duration(seconds: 1), (timer) { if (secondsElapsed > timeToPassengerFromDriverAfterApplied || !isTimerFromDriverToPassengerAfterAppliedRunning) { timer.cancel(); isTimerRunning = false; _timerStreamController.close(); // Close the stream when done return; } secondsElapsed++; _timerStreamController.add(secondsElapsed); // Emit elapsed time // Calculate progress and remaining time progressTimerToPassengerFromDriverAfterApplied = secondsElapsed / timeToPassengerFromDriverAfterApplied; remainingTimeToPassengerFromDriverAfterApplied = timeToPassengerFromDriverAfterApplied - secondsElapsed; // Update remaining time as string int minutes = (remainingTimeToPassengerFromDriverAfterApplied / 60).floor(); int seconds = remainingTimeToPassengerFromDriverAfterApplied % 60; stringRemainingTimeToPassenger = '$minutes:${seconds.toString().padLeft(2, '0')}'; if (remainingTimeToPassengerFromDriverAfterApplied < 59 && !rideTimerBegin) { rideTimerBegin = true; } // Call periodic functions if (secondsElapsed % beginRideInterval == 0) { getBeginRideFromDriver(); uploadPassengerLocation(); } update(); // Notify listeners }); } // void startTimerFromDriverToPassengerAfterApplied() async { // if (isTimerRunning) return; // Exit if timer is already running // isTimerRunning = true; // Set the flag to true // int secondsElapsed = 0; // while (secondsElapsed <= timeToPassengerFromDriverAfterApplied && // isTimerFromDriverToPassengerAfterAppliedRunning) { // await Future.delayed(const Duration(seconds: 1)); // secondsElapsed++; // progressTimerToPassengerFromDriverAfterApplied = // secondsElapsed / timeToPassengerFromDriverAfterApplied; // remainingTimeToPassengerFromDriverAfterApplied = // timeToPassengerFromDriverAfterApplied - secondsElapsed; // if (remainingTimeToPassengerFromDriverAfterApplied < 59) { // if (rideTimerBegin == false) { // rideTimerBegin = true; // } // } // // Call getBeginRideFromDriver every 4 seconds // if (secondsElapsed % beginRideInterval == 0) { // getBeginRideFromDriver(); // uploadPassengerLocation(); // } // int minutes = // (remainingTimeToPassengerFromDriverAfterApplied / 60).floor(); // int seconds = remainingTimeToPassengerFromDriverAfterApplied % 60; // stringRemainingTimeToPassenger = // '$minutes:${seconds.toString().padLeft(2, '0')}'; // update(); // } // isTimerRunning = false; // Reset the flag when timer completes // } // Remove the getBeginRideFromDriverForDuration function as it's no longer needed // Function to stop the timer void stopTimerFromDriverToPassengerAfterApplied() { isTimerFromDriverToPassengerAfterAppliedRunning = false; update(); } void startTimerDriverWaitPassenger5Minute() async { stopTimerFromDriverToPassengerAfterApplied(); isDriverArrivePassenger = true; isDriverInPassengerWay = false; timeToPassengerFromDriverAfterApplied = 0; update(); for (int i = 0; i <= 300; i++) { await Future.delayed(const Duration(seconds: 1)); progressTimerDriverWaitPassenger5Minute = i / 300; remainingTimeDriverWaitPassenger5Minute = 300 - i; int minutes = (remainingTimeDriverWaitPassenger5Minute / 60).floor(); int seconds = remainingTimeDriverWaitPassenger5Minute % 60; stringRemainingTimeDriverWaitPassenger5Minute = '$minutes:${seconds.toString().padLeft(2, '0')}'; update(); } } // Create a StreamController to manage the timer values final timerController = StreamController(); // Start the timer when the ride begins void beginRideTimer() { // Set up the timer to run every second Timer.periodic(const Duration(seconds: 1), (timer) { // Update the timer value and notify listeners timerController.add(timer.tick); update(); }); } // Stop the timer when the ride ends void stopRideTimer() { timerController.close(); update(); } late String arrivalTime = ''; void rideIsBeginPassengerTimer() async { // Calculate arrival time considering current time and duration DateTime now = DateTime.now(); DateTime arrivalTime1 = now.add(Duration(seconds: durationToRide)); arrivalTime = DateFormat('hh:mm').format(arrivalTime1); box.write(BoxName.arrivalTime, arrivalTime); for (int i = 0; i <= durationToRide; i++) { await Future.delayed(const Duration(seconds: 1)); progressTimerRideBegin = i / durationToRide; remainingTimeTimerRideBegin = durationToRide - i; if (i == (durationToRide / 4).round() && (statusRide == 'Begin')) { NotificationController().showNotification("Record Your Trip".tr, "You can call or record audio during this trip.".tr, 'tone1'); } bool sendSOS = false; if (speed > 100 && sendSOS == false) { NotificationController().showNotification( "Warning: Speeding detected!".tr, 'You can call or record audio of this trip'.tr, 'tone1'); Get.defaultDialog( barrierDismissible: false, title: "Warning: Speeding detected!".tr, titleStyle: AppStyle.title, content: Text( "We noticed the speed is exceeding 100 km/h. Please slow down for your safety. If you feel unsafe, you can share your trip details with a contact or call the police using the red SOS button." .tr, style: AppStyle.title, ), confirm: MyElevatedButton( title: "Share Trip Details".tr, onPressed: () { Get.back(); // Implement sharing trip details logic here String message = "**Emergency SOS from Passenger:**\n"; // Get trip details from GetX or relevant provider String origin = passengerLocation.toString(); String destination = myDestination.toString(); String driverName = passengerName; String driverCarPlate = licensePlate; // Add trip details to the message message += "* ${'Origin'.tr}: $origin\n"; message += "* ${'Destination'.tr}: $destination\n"; message += "* ${'Driver Name'.tr}: $driverName\n"; message += "* ${'Driver Car Plate'.tr}: $driverCarPlate\n\n"; message += "* ${'Driver phone'.tr}:$driverPhone\n\n"; // Add any additional information you want to include (optional) // - Example: current location (using GetX LocationController) message += "${'Current Location'.tr}:https://www.google.com/maps/place/${passengerLocation.latitude},${passengerLocation.longitude} \n"; // Append a call to action message += "Please help! Contact me as soon as possible.".tr; // Launch WhatsApp communication with the constructed message launchCommunication( 'whatsapp', box.read(BoxName.sosPhonePassenger), message); sendSOS = true; }, kolor: AppColor.redColor, ), cancel: MyElevatedButton( title: "Cancel".tr, onPressed: () { Get.back(); }, kolor: AppColor.greenColor, ), ); } int minutes = (remainingTimeTimerRideBegin / 60).floor(); int seconds = remainingTimeTimerRideBegin % 60; stringRemainingTimeRideBegin = '$minutes:${seconds.toString().padLeft(2, '0')}'; update(); } // rideTimerBegin = false; // isRideFinished = true; // update(); } int progressTimerRideBeginVip = 0; int elapsedTimeInSeconds = 0; // Timer starts from 0 String stringElapsedTimeRideBegin = '0:00'; String stringElapsedTimeRideBeginVip = '0:00'; bool rideInProgress = true; // To control when to stop the timer void rideIsBeginPassengerTimerVIP() async { rideInProgress = true; // Start the ride timer bool sendSOS = false; while (rideInProgress) { await Future.delayed(const Duration(seconds: 1)); // Increment elapsed time elapsedTimeInSeconds++; // Update the time display int minutes = (elapsedTimeInSeconds / 60).floor(); int seconds = elapsedTimeInSeconds % 60; stringElapsedTimeRideBeginVip = '$minutes:${seconds.toString().padLeft(2, '0')}'; // Check for speed and SOS conditions if (speed > 100 && !sendSOS) { Get.defaultDialog( barrierDismissible: false, title: "Warning: Speeding detected!".tr, titleStyle: AppStyle.title, content: Text( "We noticed the speed is exceeding 100 km/h. Please slow down for your safety. If you feel unsafe, you can share your trip details with a contact or call the police using the red SOS button." .tr, style: AppStyle.title, ), confirm: MyElevatedButton( title: "Share Trip Details".tr, onPressed: () { Get.back(); // Implement sharing trip details logic here String message = "**Emergency SOS from Passenger:**\n"; // Get trip details from GetX or relevant provider String origin = passengerLocation.toString(); String destination = myDestination.toString(); String driverName = passengerName; String driverCarPlate = licensePlate; // Add trip details to the message message += "* ${'Origin'.tr}: $origin\n"; message += "* ${'Destination'.tr}: $destination\n"; message += "* ${'Driver Name'.tr}: $driverName\n"; message += "* ${'Driver Car Plate'.tr}: $driverCarPlate\n\n"; message += "* ${'Driver Phone'.tr}: $driverPhone\n\n"; // Add current location message += "${'Current Location'.tr}:https://www.google.com/maps/place/${passengerLocation.latitude},${passengerLocation.longitude} \n"; // Append a call to action message += "Please help! Contact me as soon as possible.".tr; // Launch WhatsApp communication launchCommunication( 'whatsapp', box.read(BoxName.sosPhonePassenger), message); sendSOS = true; }, kolor: AppColor.redColor, ), cancel: MyElevatedButton( title: "Cancel".tr, onPressed: () { Get.back(); }, kolor: AppColor.greenColor, ), ); } // Update the UI update(); } } void tripFinishedFromDriver() { isRideFinished = true; rideTimerBegin = false; statusRideVip = 'Finished'; box.write(BoxName.arrivalTime, ''); remainingTimeTimerRideBegin = 0; box.write(BoxName.passengerWalletTotal, '0'); update(); if (box.read(BoxName.parentTripSelected) == true) { FirebaseMessagesController().sendNotificationToPassengerToken( "Finish Monitor".tr, "Finish Monitor".tr, box.read(BoxName.tokenParent), [], 'order1.wav', ); box.write(BoxName.parentTripSelected, false); box.remove(BoxName.tokenParent); } } // bool isBeginRideFromDriver = false; // void getBeginRideFromDriver() async { // try { // if (isBeginRideFromDriver) return; // Prevent duplicate streams // isBeginRideFromDriver = true; // var res = await CRUD() // .get(link: AppLink.getRideStatusBegin, payload: {'ride_id': rideId}); // if (res != 'failure') { // var decode = jsonDecode(res); // // if (decode['data']['status'] != 'Apply') { // if (decode['data']['status'] == 'Begin') { // timeToPassengerFromDriverAfterApplied = 0; // remainingTime = 0; // remainingTimeToPassengerFromDriverAfterApplied = 0; // remainingTimeDriverWaitPassenger5Minute = 0; // rideTimerBegin = true; // statusRide = 'Begin'; // isDriverInPassengerWay = false; // isDriverArrivePassenger = false; // update(); // // isCancelRidePageShown = true; // rideIsBeginPassengerTimer(); // runWhenRideIsBegin(); // } else {} // } // } catch (e) { // // Handle the error or perform any necessary actions // } // } StreamController _beginRideStreamController = StreamController.broadcast(); Stream get beginRideStream => _beginRideStreamController.stream; bool isBeginRideFromDriverRunning = false; void getBeginRideFromDriver() { if (isBeginRideFromDriverRunning) return; // Prevent duplicate streams isBeginRideFromDriverRunning = true; Timer.periodic(const Duration(seconds: 1), (timer) async { try { var res = await CRUD().get( link: AppLink.getRideStatusBegin, payload: {'ride_id': rideId}); print(res); print('1002'); if (res != 'failure') { var decode = jsonDecode(res); _beginRideStreamController .add(decode['data']['status']); // Emit the status if (decode['data']['status'] == 'Begin') { // Stop the periodic check timer.cancel(); isBeginRideFromDriverRunning = false; timeToPassengerFromDriverAfterApplied = 0; remainingTime = 0; remainingTimeToPassengerFromDriverAfterApplied = 0; remainingTimeDriverWaitPassenger5Minute = 0; rideTimerBegin = true; statusRide = 'Begin'; isDriverInPassengerWay = false; isDriverArrivePassenger = false; update(); // Trigger additional actions rideIsBeginPassengerTimer(); runWhenRideIsBegin(); NotificationController().showNotification( 'Trip is begin'.tr, 'The trip has started! Feel free to contact emergency numbers, share your trip, or activate voice recording for the journey' .tr, 'ding'); } } } catch (e) { // Handle errors _beginRideStreamController.addError(e); } }); } // Call this method to listen to the stream void listenToBeginRideStream() { beginRideStream.listen((status) { print("Ride status: $status"); // Perform additional actions based on the status }, onError: (error) { print("Error in Begin Ride Stream: $error"); }); } begiVIPTripFromPassenger() async { timeToPassengerFromDriverAfterApplied = 0; remainingTime = 0; isBottomSheetShown = false; remainingTimeToPassengerFromDriverAfterApplied = 0; remainingTimeDriverWaitPassenger5Minute = 0; rideTimerBegin = true; statusRideVip = 'Begin'; isDriverInPassengerWay = false; isDriverArrivePassenger = false; update(); // isCancelRidePageShown = true; rideIsBeginPassengerTimerVIP(); runWhenRideIsBegin(); } Map rideStatusFromStartApp = {}; getRideStatusFromStartApp() async { try { var res = await CRUD().get( link: AppLink.getRideStatusFromStartApp, payload: {'passenger_id': box.read(BoxName.passengerID)}); print(res); print('1070'); if (res == 'failure') { print( "No rides found for the given passenger ID within the last hour."); } rideStatusFromStartApp = jsonDecode(res); if (rideStatusFromStartApp['data']['status'] == 'Begin') { statusRide = 'Begin'; driverId = rideStatusFromStartApp['data']['driver_id']; passengerName = rideStatusFromStartApp['data']['driverName']; driverRate = rideStatusFromStartApp['data']['rateDriver'].toString(); statusRideFromStart = true; // DateTime endTime = // DateTime.parse(rideStatusFromStartApp['data']['endtime']); // DateTime rideTimeStart = // DateTime.parse(rideStatusFromStartApp['data']['rideTimeStart']); // // // Calculate the new end time by adding the duration to the rideTimeStart // DateTime newEndTime = rideTimeStart.add( // Duration(seconds: endTime.difference(rideTimeStart).inSeconds)); // // // Save the new end time in a variable // var newEndTimeVariable = newEndTime.toString(); update(); Map tripData = box.read(BoxName.tripData) as Map; final points = decodePolyline( tripData["routes"][0]["overview_polyline"]["points"]); for (int i = 0; i < points.length; i++) { double lat = points[i][0].toDouble(); double lng = points[i][1].toDouble(); polylineCoordinates.add(LatLng(lat, lng)); } var polyline = Polyline( polylineId: const PolylineId('begin trip'), points: polylineCoordinates, width: 10, color: Colors.blue, ); polyLines.add(polyline); timeToPassengerFromDriverAfterApplied = 0; remainingTime = 0; remainingTimeToPassengerFromDriverAfterApplied = 0; remainingTimeDriverWaitPassenger5Minute = 0; rideTimerBegin = true; isDriverInPassengerWay = false; isDriverArrivePassenger = false; // update(); // isCancelRidePageShown = true; durationToAdd = tripData['routes'][0]['legs'][0]['duration']['value']; rideIsBeginPassengerTimer(); runWhenRideIsBegin(); update(); } } catch (e) { // Handle the error or perform any necessary actions } } void driverArrivePassenger() { timeToPassengerFromDriverAfterApplied = 0; remainingTime = 0; // isCancelRidePageShown = true; update(); rideIsBeginPassengerTimer(); // runWhenRideIsBegin(); } void cancelTimerToPassengerFromDriverAfterApplied() { timerToPassengerFromDriverAfterApplied?.cancel(); } void clearPlacesDestination() { placesDestination = []; hintTextDestinationPoint = 'Search for your destination'.tr; update(); } void clearPlacesStart() { placesStart = []; hintTextStartPoint = 'Search for your Start point'.tr; update(); } void clearPlaces(int index) { placeListResponseAll[index] = []; hintTextwayPointStringAll[index] = 'Search for waypoint'.tr; update(); } void clearPlaces1() { wayPoint1 = []; hintTextwayPoint1 = 'Search for waypoint'.tr; update(); } void clearPlaces2() { wayPoint2 = []; hintTextwayPoint2 = 'Search for waypoint'.tr; update(); } void clearPlaces3() { wayPoint3 = []; hintTextwayPoint3 = 'Search for waypoint'.tr; update(); } void clearPlaces4() { wayPoint4 = []; hintTextwayPoint4 = 'Search for waypoint'.tr; update(); } int selectedReason = -1; String? cancelNote; void selectReason(int index, String note) { selectedReason = index; cancelNote = note; update(); } void getDialog(String title, String? midTitle, VoidCallback onPressed) { final textToSpeechController = Get.find(); Get.defaultDialog( title: title, titleStyle: AppStyle.title, middleTextStyle: AppStyle.title, content: Column( children: [ IconButton( onPressed: () async { await textToSpeechController.speakText(title ?? midTitle!); }, icon: const Icon(Icons.headphones)), Text( midTitle!, style: AppStyle.title, ) ], ), confirm: MyElevatedButton( title: 'Ok'.tr, onPressed: onPressed, kolor: AppColor.greenColor, ), cancel: MyElevatedButton( title: 'Cancel', kolor: AppColor.redColor, onPressed: () { Get.back(); })); } Map? extractCoordinatesFromLink(String link) { try { // Extract the URL part from the link by finding the first occurrence of "http" int urlStartIndex = link.indexOf(RegExp(r'https?://')); if (urlStartIndex == -1) { throw const FormatException('No URL found in the provided link.'); } // Extract the URL and clean it link = link.substring(urlStartIndex).trim(); Uri uri = Uri.parse(link); // Common coordinate query parameters List coordinateParams = ['q', 'cp', 'll']; // Try to extract coordinates from query parameters for (var param in coordinateParams) { String? value = uri.queryParameters[param]; if (value != null && (value.contains(',') || value.contains('~'))) { List coordinates = value.contains(',') ? value.split(',') : value.split('~'); if (coordinates.length == 2) { double? latitude = double.tryParse(coordinates[0].trim()); double? longitude = double.tryParse(coordinates[1].trim()); if (latitude != null && longitude != null) { return { 'latitude': latitude, 'longitude': longitude, }; } } } } // Try to extract coordinates from the path List pathSegments = uri.pathSegments; for (var segment in pathSegments) { if (segment.contains(',')) { List coordinates = segment.split(','); if (coordinates.length == 2) { double? latitude = double.tryParse(coordinates[0].trim()); double? longitude = double.tryParse(coordinates[1].trim()); if (latitude != null && longitude != null) { return { 'latitude': latitude, 'longitude': longitude, }; } } } } } catch (e) { print('Error parsing location link: $e'); } return null; } double latitudeWhatsApp = 0; double longitudeWhatsApp = 0; void handleWhatsAppLink(String link) { Map? coordinates = extractCoordinatesFromLink(link); if (coordinates != null) { latitudeWhatsApp = coordinates['latitude']!; longitudeWhatsApp = coordinates['longitude']!; print( 'Extracted coordinates: Lat: $latitudeWhatsApp, Long: $longitudeWhatsApp'); // Use these coordinates in your app as needed } else { print('Failed to extract coordinates from the link'); } } void goToWhatappLocation() async { if (sosFormKey.currentState!.validate()) { changeIsWhatsAppOrder(true); Get.back(); handleWhatsAppLink(whatsAppLocationText.text); myDestination = LatLng(latitudeWhatsApp, longitudeWhatsApp); await mapController?.animateCamera(CameraUpdate.newLatLng( LatLng(passengerLocation.latitude, passengerLocation.longitude))); changeMainBottomMenuMap(); passengerStartLocationFromMap = true; isPickerShown = true; update(); } } int currentTimeSearchingCaptainWindow = 0; late String driverPhone = ''; late String driverRate = ''; late String passengerName = ''; late String carColor = ''; late String colorHex = ''; late String carYear = ''; late String model = ''; late String make = ''; late String licensePlate = ''; String driverOrderStatus = 'yet'; bool isDriversTokensSend = false; Set notifiedDrivers = {}; addRideToNotificationDriverAvailable() async { await CRUD().post(link: AppLink.addWaitingRide, payload: { 'id': rideId.toString(), '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(), "price": totalPassenger.toStringAsFixed(2), 'passenger_id': box.read(BoxName.passengerID).toString(), 'status': 'waiting', 'carType': box.read(BoxName.carType), 'passengerRate': passengerRate.toStringAsFixed(2), 'price_for_passenger': totalME.toStringAsFixed(2), 'distance': distance.toStringAsFixed(1), 'duration': duration.toStringAsFixed(1), }); if (AppLink.endPoint != AppLink.seferCairoServer) { CRUD().post( link: '${AppLink.endPoint}/notificationCaptain/addWaitingRide.php', payload: { 'id': rideId.toString(), '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(), "price": totalPassenger.toStringAsFixed(2), 'passenger_id': box.read(BoxName.passengerID).toString(), 'status': 'waiting', 'carType': box.read(BoxName.carType), 'passengerRate': passengerRate.toStringAsFixed(2), 'price_for_passenger': totalME.toStringAsFixed(2), 'distance': distance.toStringAsFixed(1), 'duration': duration.toStringAsFixed(0), }); } } // Future confirmRideForAllDriverAvailable1() async { // // Try to fetch car locations up to 4 times with a 2-second delay // bool driversFound = false; // for (int attempt = 0; attempt < 8; attempt++) { // await getCarsLocationByPassengerAndReloadMarker( // box.read(BoxName.carType), attempt > 5 ? 4500 : 3000); // // Check if dataCarsLocationByPassenger is valid and contains drivers // if (dataCarsLocationByPassenger != 'failure' && // dataCarsLocationByPassenger != null && // dataCarsLocationByPassenger.containsKey('data') && // dataCarsLocationByPassenger['message'] != null) { // driversFound = true; // break; // Exit loop if drivers are found // } // // 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['message'][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 != null && // dataCarsLocationByPassenger.containsKey('data') && // dataCarsLocationByPassenger['message'] != null) { // for (var driverData in dataCarsLocationByPassenger['message']) { // 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']}', // totalPassenger.toStringAsFixed(2), // totalDriver.toStringAsFixed(2), // durationToRide.toString(), // distance.toStringAsFixed(2), // driverId.toString(), // box.read(BoxName.passengerID).toString(), // box.read(BoxName.name).toString(), // box.read(BoxName.tokenFCM).toString(), // box.read(BoxName.phone).toString(), // durationByPassenger.toString(), // distanceByPassenger.toString(), // paymentController.isWalletChecked.toString(), // driverData['token'].toString(), // durationToPassenger.toString(), // rideId.toString(), // rideTimerBegin.toString(), // driverId.toString(), // durationToRide.toString(), // Get.find().wayPoints.length > 1 // ? 'haveSteps' // : 'startEnd', // placesCoordinate[0], // placesCoordinate[1], // placesCoordinate[2], // placesCoordinate[3], // placesCoordinate[4], // costForDriver.toStringAsFixed(2), // (double.parse(box.read(BoxName.passengerWalletTotal)) < 0 // ? double.parse(box.read(BoxName.passengerWalletTotal)) // .toStringAsFixed(2) // : '0'), // box.read(BoxName.email).toString(), // data[0]['start_address'], // data[0]['end_address'], // box.read(BoxName.carType), // kazan.toStringAsFixed(0), // passengerRate.toStringAsFixed(2), // ]; // Log.print('body: ${body}'); // FirebaseMessagesController().sendNotificationToDriverMAP( // 'OrderSpeed', // rideId, // driverData['token'].toString(), // body, // 'order.wav', // ); // } // } // } // }); // }); // // 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['message'][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(); // } increaseForSameRideAndDelay() async { reSearchAfterCanceledFromDriver(); // bool driversFound = false; // for (int attempt = 0; attempt < 8; attempt++) { // await getCarsLocationByPassengerAndReloadMarker( // box.read(BoxName.carType), 4500); // // Check if dataCarsLocationByPassenger is valid and contains drivers // if (dataCarsLocationByPassenger != 'failure' && // dataCarsLocationByPassenger != null && // dataCarsLocationByPassenger.containsKey('message') && // dataCarsLocationByPassenger['message'] != null) { // driversFound = true; // break; // Exit loop if drivers are found // } // // 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; // } // PaymentController paymentController = Get.find(); // rideConfirm = true; // shouldFetch = true; // isBottomSheetShown = false; // timeToPassengerFromDriverAfterApplied = 60; // // confirmRideForAllDriverAvailable(); // for (var i = 0; i < dataCarsLocationByPassenger['message'].length; i++) { // List body = [ // '${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}', // '${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}', // totalPassenger.toStringAsFixed(2), // totalDriver.toStringAsFixed(2), // durationToRide.toString(), // distance.toStringAsFixed(2), // dataCarsLocationByPassenger['message'][i]['driver_id'].toString(), // box.read(BoxName.passengerID).toString(), // box.read(BoxName.name).toString(), // box.read(BoxName.tokenFCM).toString(), // box.read(BoxName.phone).toString(), // durationByPassenger.toString(), // distanceByPassenger.toString(), // paymentController.isWalletChecked.toString(), // dataCarsLocationByPassenger['message'][i]['token'].toString(), // durationToPassenger.toString(), // rideId.toString(), // rideTimerBegin.toString(), // dataCarsLocationByPassenger['message'][i]['driver_id'].toString(), // durationToRide.toString(), // Get.find().wayPoints.length > 1 // ? 'haveSteps' // : 'startEnd', // placesCoordinate[0], // placesCoordinate[1], // placesCoordinate[2], // placesCoordinate[3], // placesCoordinate[4], // costForDriver.toStringAsFixed(2), // double.parse(box.read(BoxName.passengerWalletTotal)) < 0 // ? double.parse(box.read(BoxName.passengerWalletTotal)) // .toStringAsFixed(2) // : '0', // box.read(BoxName.email).toString(), // data[0]['start_address'], // data[0]['end_address'], // box.read(BoxName.carType), // kazan.toStringAsFixed(0), // passengerRate.toStringAsFixed(2), // ]; // // Log.print('body: ${body}'); // FirebaseMessagesController().sendNotificationToDriverMAP( // 'OrderSpeed', // rideId.toString(), // dataCarsLocationByPassenger['message'][i]['token'].toString(), // body, // 'order.wav'); // } } int tick = 0; // Move tick outside the function to maintain its state // void delayAndFetchRideStatus(String rideId, carType) { // Timer.periodic(const Duration(seconds: 1), (timer) async { // if (shouldFetch) { // if (remainingTimeToPassengerFromDriverAfterApplied > 0) { // String res = await getRideStatus(rideId); // Log.print('tick: $tick'); // String rideStatusDelayed = res.toString(); // if ((rideStatusDelayed == 'waiting' || // rideStatusDelayed == 'Refused') && // tick >= 15) { // timer.cancel(); // Stop the current timer // showAndResearchForCaptain(); // //TODO add to wait // await getCarsLocationByPassengerAndReloadMarker(carType, 3000); // // await getNearestDriverByPassengerLocationAPIGOOGLE(); // // getCarForFirstConfirm(carType); // confirmRideForAllDriverAvailable(); // // delayAndFetchRideStatusForAllDriverAvailable(rideId); // } else if (rideStatusDelayed == 'Apply' || statusRide == 'Apply') { // Log.print('rideStatusDelayed == Apply: $rideStatusDelayed'); // // todo play sound // Get.find() // .playSoundFromAssets('assets/start.wav'); // timer.cancel(); // Stop the current timer // await getUpdatedRideForDriverApply(rideId); // shouldFetch = false; // Stop further fetches // statusRide = 'Apply'; // rideConfirm = false; // isSearchingWindow = false; // update(); // startTimerFromDriverToPassengerAfterApplied(); // if (box.read(BoxName.carType) == 'Speed' || // box.read(BoxName.carType) == 'Awfar Car') { // NotificationController().showNotification( // 'The captain is responsible for the route.'.tr, // 'This price is fixed even if the route changes for the driver.' // .tr, // 'ding'); // } else if (box.read(BoxName.carType) == 'Comfort' || // box.read(BoxName.carType) == 'Lady') { // NotificationController().showNotification('Attention'.tr, // 'The price may increase if the route changes.'.tr, 'ding'); // } // } else if (rideStatusDelayed == 'Refused') { // statusRide = 'Refused'; // if (isDriversTokensSend == false) { // confirmRideForAllDriverAvailable(); // isDriversTokensSend = true; // } // Start 15-second timer // } // //else if (isDriversTokensSend == false) { // // No need to recall delayAndFetchRideStatus as Timer.periodic is already running // update(); // // } // if (tick < 19) { // tick++; // } else { // timer.cancel(); // // Stop the timer if remainingTimeToPassengerFromDriverAfterApplied <= 0 // } // } else { // timer.cancel(); // // Stop the timer if remainingTimeToPassengerFromDriverAfterApplied <= 0 // } // } else { // timer.cancel(); // Stop the timer if shouldFetch is false // } // }); // } showAndResearchForCaptain() { Get.snackbar( "No Captain Accepted Your Order".tr, "We are looking for a captain but the price may increase to let a captain accept" .tr, duration: const Duration(seconds: 5), backgroundColor: AppColor.yellowColor, ); isSearchingWindow == true; update(); } String driversStatusForSearchWindow = ''; Future confirmRideForAllDriverAvailable() async { bool driversFound = false; const maxAttempts = 8; const attemptDelay = Duration(seconds: 3); for (int attempt = 0; attempt < maxAttempts; attempt++) { final reloadDuration = attempt > 5 ? 4500 : 3000; await getCarsLocationByPassengerAndReloadMarker( box.read(BoxName.carType), reloadDuration); // await getNearestDriverByPassengerLocation(); driversStatusForSearchWindow = 'We are search for nearst driver'.tr; if (isDriversDataValid()) { driversFound = true; break; } await Future.delayed(attemptDelay); } if (!driversFound) { showNoDriversDialog(); return; } driversStatusForSearchWindow = 'Your order is being prepared'.tr; Log.print('driversStatusForSearchWindow: ${driversStatusForSearchWindow}'); update(); await postRideDetailsToServer(); driversStatusForSearchWindow = 'Your order sent to drivers'.tr; await notifyAvailableDrivers(); driversStatusForSearchWindow = 'The drivers are reviewing your request'.tr; Log.print('driversStatusForSearchWindow: ${driversStatusForSearchWindow}'); update(); delayAndFetchRideStatusForAllDriverAvailable(rideId); update(); } Future updateConfirmRideForAllDriverAvailable() async { bool driversFound = false; const maxAttempts = 8; const attemptDelay = Duration(seconds: 3); for (int attempt = 0; attempt < maxAttempts; attempt++) { final reloadDuration = attempt > 5 ? 4500 : 3000; await getCarsLocationByPassengerAndReloadMarker( box.read(BoxName.carType), reloadDuration); // await getNearestDriverByPassengerLocation(); if (isDriversDataValid()) { driversFound = true; break; } await Future.delayed(attemptDelay); } if (!driversFound) { showNoDriversDialog(); return; } // await postRideDetailsToServer(); await notifyAvailableDrivers(); delayAndFetchRideStatusForAllDriverAvailable(rideId); update(); } bool isDriversDataValid() { return dataCarsLocationByPassenger != 'failure' && dataCarsLocationByPassenger != null && dataCarsLocationByPassenger.containsKey('message') && dataCarsLocationByPassenger['message'] != null; } void showNoDriversDialog() { 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, ); } Future postRideDetailsToServer() async { final paymentController = Get.find(); final payload = constructRidePayload(paymentController); try { final response = await CRUD().post( link: "${AppLink.seferCairoServer}/ride/rides/add.php", payload: payload); if (response is String) { final parsedValue = jsonDecode(response); rideId = parsedValue['message']; } else if (response is Map) { rideId = response['message']; } else { Log.print('Unexpected response type: ${response.runtimeType}'); } } catch (e) { Log.print('Error posting ride details: $e'); } } Map constructRidePayload( PaymentController paymentController) { final startLocation = '${data[0]['start_location']['lat']},${data[0]['start_location']['lng']}'; final endLocation = '${data[0]['end_location']['lat']},${data[0]['end_location']['lng']}'; return { "start_location": startLocation, "end_location": endLocation, "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['message'][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(), }; } Future notifyAvailableDrivers() async { int iteration = 0; const maxIterations = 5; const iterationDelay = Duration(seconds: 2); while (iteration < maxIterations) { await Future.delayed(iterationDelay); await getCarsLocationByPassengerAndReloadMarker( box.read(BoxName.carType), 3000); if (dataCarsLocationByPassenger != null && dataCarsLocationByPassenger.containsKey('message') && dataCarsLocationByPassenger['message'] != null) { for (var driverData in dataCarsLocationByPassenger['message']) { String driverId = driverData['driver_id'].toString(); if (!notifiedDrivers.contains(driverId)) { notifiedDrivers.add(driverId); double driverLat = double.parse(driverData['latitude']); double driverLng = double.parse(driverData['longitude']); double distanceToDriverInMeters = Geolocator.distanceBetween( passengerLocation.latitude, passengerLocation.longitude, driverLat, driverLng, ); double distanceToDriverInKm = distanceToDriverInMeters * 1.25 / //to approximate to stright distance 1000; double durationToDriverInHours = distanceToDriverInKm / 25; // 25 km/h as default speed double durationToDriverInSeconds = durationToDriverInHours * 3600; durationToPassenger = durationToDriverInSeconds.toInt(); distanceByPassenger = (distanceToDriverInMeters * 1.25).toStringAsFixed(0); Future.delayed(const Duration(microseconds: 10)); final body = constructNotificationBody(driverData); // Log.print('body:ww ${body}'); FirebaseMessagesController().sendNotificationToDriverMAP( 'OrderSpeed', rideId, driverData['token'].toString(), body, 'order.wav'); } } } iteration++; } } List constructNotificationBody(var driverData) { final paymentController = Get.find(); return [ '${data[0]['start_location']['lat']},${data[0]['start_location']['lng']}', '${data[0]['end_location']['lat']},${data[0]['end_location']['lng']}', totalPassenger.toStringAsFixed(2), totalDriver.toStringAsFixed(2), durationToRide.toString(), distance.toStringAsFixed(2), driverData['driver_id'].toString(), box.read(BoxName.passengerID).toString(), box.read(BoxName.name).toString(), box.read(BoxName.tokenFCM).toString(), box.read(BoxName.phone).toString(), durationToPassenger.toStringAsFixed(0) ?? '120', distanceByPassenger.toString() ?? '2000', paymentController.isWalletChecked.toString(), driverData['token'].toString(), durationToPassenger.toString(), rideId.toString(), rideTimerBegin.toString(), driverData['driver_id'].toString(), durationToRide.toString(), Get.find().wayPoints.length > 1 ? 'haveSteps' : 'startEnd', placesCoordinate[0], placesCoordinate[1], placesCoordinate[2], placesCoordinate[3], placesCoordinate[4], costForDriver.toStringAsFixed(2), (double.parse(box.read(BoxName.passengerWalletTotal)) < 0 ? double.parse(box.read(BoxName.passengerWalletTotal)) .toStringAsFixed(2) : '0'), box.read(BoxName.email).toString(), data[0]['start_address'], data[0]['end_address'], box.read(BoxName.carType), kazan.toStringAsFixed(0), passengerRate.toStringAsFixed(2), ]; } StreamController _rideStatusStreamController = StreamController.broadcast(); Stream get rideStatusStream => _rideStatusStreamController.stream; Future delayAndFetchRideStatusForAllDriverAvailable( String rideId) async { const int maxAttempts = 15; int attemptCounter = 0; bool isApplied = false; tick = 0; await addRideToNotificationDriverAvailable(); Timer.periodic(const Duration(seconds: 1), (timer) async { if (attemptCounter >= maxAttempts || isApplied) { timer.cancel(); _rideStatusStreamController.close(); // Close the stream when done return; } attemptCounter++; tick++; try { var res = await getRideStatus(rideId); Log.print('res:2022 ${res}'); String rideStatusDelayed = res.toString(); Log.print('rideStatusDelayed: ${rideStatusDelayed}'); _rideStatusStreamController .add(rideStatusDelayed); // Emit the ride status // addRideToNotificationDriverString(); if (rideStatusDelayed == 'Cancel') { timer.cancel(); NotificationController().showNotification( "Order Cancelled".tr, "you canceled order".tr, 'ding'); _rideStatusStreamController .close(); // Close stream after cancellation // // } else if (rideStatusDelayed == 'Apply' || rideStatusDelayed == 'Applied') { rideAppliedFromDriver(isApplied); timer.cancel(); // Close stream after applying } else if (attemptCounter >= maxAttempts || rideStatusDelayed != 'Cancel') { timer.cancel(); //todo // addRideToNotificationDriverString(); // Show dialog to increase fee... MyDialog().getDialog( 'Are you want to wait drivers to accept your order'.tr, '', () { Get.back(); addRideToNotificationDriverAvailable(); }); update(); _rideStatusStreamController .close(); // Close stream after max attempts } } catch (e) { _rideStatusStreamController.addError(e); // Handle errors in the stream } }); } rideAppliedFromDriver(bool isApplied) async { 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'); if (box.read(BoxName.carType) == 'Speed' || box.read(BoxName.carType) == 'Awfar Car') { NotificationController().showNotification( 'The captain is responsible for the route.'.tr, 'This price is fixed even if the route changes for the driver.'.tr, 'ding'); } else if (box.read(BoxName.carType) == 'Comfort' || box.read(BoxName.carType) == 'Lady') { NotificationController().showNotification('Attention'.tr, 'The price may increase if the route changes.'.tr, 'ding'); } isApplied = true; statusRide = 'Apply'; rideConfirm = false; isSearchingWindow = false; update(); startTimer(); // todo stop this because this method in startTimer() // startTimerFromDriverToPassengerAfterApplied(); // timer.cancel(); _rideStatusStreamController.close(); } // Listening to the Stream void listenToRideStatusStream() { rideStatusStream.listen((rideStatus) { print("Ride Status: $rideStatus"); // Handle updates based on the ride status }, onError: (error) { print("Error in Ride Status Stream: $error"); // Handle stream errors }, onDone: () { print("Ride status stream closed."); }); } reSearchAfterCanceledFromDriver() async { shouldFetch = true; // Stop further fetches statusRide = 'wait'; rideConfirm = true; isSearchingWindow = true; update(); updateConfirmRideForAllDriverAvailable(); } void start15SecondTimer(String rideId) { Timer(const Duration(seconds: 15), () { delayAndFetchRideStatusForAllDriverAvailable(rideId); }); } void startTimer() async { for (int i = 0; i <= durationTimer; i++) { await Future.delayed(const Duration(seconds: 1)); progress = i / durationTimer; remainingTime = durationTimer - i; if (remainingTime == 0) { rideConfirm = false; timeToPassengerFromDriverAfterApplied += durationToPassenger; // timeToPassengerFromDriverAfterApplied.toString()); startTimerFromDriverToPassengerAfterApplied(); update(); } update(); } timerEnded(); } void timerEnded() async { runEvery30SecondsUntilConditionMet(); isCancelRidePageShown = false; print('isCancelRidePageShown: $isCancelRidePageShown'); update(); } Future getRideStatus(String rideId) async { final response = await CRUD().get( link: "${AppLink.endPoint}/ride/rides/getRideStatus.php", payload: {'id': rideId}); print(response); print('2140'); return jsonDecode(response)['data']; } late String driverCarModel, driverCarMake, driverLicensePlate, driverName = ''; getUpdatedRideForDriverApply(String rideId) async { // if (isDriversTokensSend) { final res = await CRUD().get( link: "${AppLink.endPoint}/ride/rides/getRideOrderID.php", payload: {'id': rideId}); if (res != 'failure') { var response = jsonDecode(res); Log.print('getUpdatedRideForDriverApply: $response'); driverId = response['data']['driver_id']; driverPhone = response['data']['phone']; driverCarMake = response['data']['make']; model = response['data']['model']; colorHex = response['data']['color_hex']; carColor = response['data']['color']; make = response['data']['make']; licensePlate = response['data']['car_plate']; passengerName = response['data']['passengerName']; driverName = response['data']['driverName'].toString(); driverToken = response['data']['token']; // Log.print('driverToken updated: $driverToken'); carYear = response['data']['year']; driverRate = response['data']['ratingDriver'].toString(); } // driversToken.remove(driverToken); // for (var i = 1; i < driversToken.length; i++) { FirebaseMessagesController().sendNotificationToDriverMAP( 'Order Accepted'.tr, '$driverName${'Accepted your order'.tr}', driverToken.toString(), [], 'start.wav', ); // } // } } late LatLng currentDriverLocation; late double headingList; // Future getCarsLocationByPassengerAndReloadMarker() async { // if (statusRide == 'wait') { // carsLocationByPassenger = []; // LatLngBounds bounds = calculateBounds( // passengerLocation.latitude, passengerLocation.longitude, 7000); // var res; // if (box.read(BoxName.carType) == 'Lady') { // res = await CRUD() // .get(link: AppLink.getFemalDriverLocationByPassenger, payload: { // 'southwestLat': bounds.southwest.latitude.toString(), // 'southwestLon': bounds.southwest.longitude.toString(), // 'northeastLat': bounds.northeast.latitude.toString(), // 'northeastLon': bounds.northeast.longitude.toString(), // }); // } else if (box.read(BoxName.carType) == 'Speed') { // res = await CRUD().get( // link: AppLink.getCarsLocationByPassengerSpeed, // payload: { // 'southwestLat': bounds.southwest.latitude.toString(), // 'southwestLon': bounds.southwest.longitude.toString(), // 'northeastLat': bounds.northeast.latitude.toString(), // 'northeastLon': bounds.northeast.longitude.toString(), // }, // ); // } else if (box.read(BoxName.carType) == 'Delivery') { // res = await CRUD().get( // link: AppLink.getCarsLocationByPassengerDelivery, // payload: { // 'southwestLat': bounds.southwest.latitude.toString(), // 'southwestLon': bounds.southwest.longitude.toString(), // 'northeastLat': bounds.northeast.latitude.toString(), // 'northeastLon': bounds.northeast.longitude.toString(), // }, // ); // } else { // res = await CRUD() // .get(link: AppLink.getCarsLocationByPassenger, payload: { // 'southwestLat': bounds.southwest.latitude.toString(), // 'southwestLon': bounds.southwest.longitude.toString(), // 'northeastLat': bounds.northeast.latitude.toString(), // 'northeastLon': bounds.northeast.longitude.toString(), // }); // } // if (res == 'failure') { // noCarString = true; // dataCarsLocationByPassenger = res; // update(); // } else { // // Get.snackbar('no car', 'message'); // noCarString = false; // dataCarsLocationByPassenger = jsonDecode(res); // // if (dataCarsLocationByPassenger.length > carsOrder) { // driverId = dataCarsLocationByPassenger['message'][carsOrder] // ['driver_id'] // .toString(); // gender = dataCarsLocationByPassenger['message'][carsOrder]['gender'] // .toString(); // // } // carsLocationByPassenger.clear(); // Clear existing markers // // late LatLng lastDriverLocation; // Initialize a variable for last location // for (var i = 0; // i < dataCarsLocationByPassenger['message'].length; // i++) { // var json = dataCarsLocationByPassenger['message'][i]; // // CarLocationModel model = CarLocationModel.fromJson(json); // if (carLocationsModels.length < i + 1) { // // carLocationsModels.add(model); // markers.add( // Marker( // markerId: MarkerId(json['latitude']), // position: LatLng( // double.parse(json['latitude']), // double.parse(json['longitude']), // ), // rotation: double.parse(json['heading']), // icon: json['model'].toString().contains('دراجة') // ? motoIcon // : json['gender'] == 'Male'.tr // ? carIcon // : ladyIcon, // ), // ); // driversToken.add(json['token']); // // driversToken = json['token']; // } else { // // carLocationsModels[i] = model; // markers[i] = Marker( // markerId: MarkerId(json['latitude']), // position: LatLng( // double.parse(json['latitude']), // double.parse(json['longitude']), // ), // rotation: double.parse(json['heading']), // icon: json['model'].contains('دراجة') // ? motoIcon // : json['gender'] == 'Male'.tr // ? carIcon // : ladyIcon, // ); // // driversToken = json['token']; // driversToken.add(json['token']); // } // } // } // update(); // } // } Map _animationTimers = {}; final int updateIntervalMs = 100; // Update every 100ms final double minMovementThreshold = 10; // Minimum movement in meters to trigger update Future getCarForFirstConfirm(String carType) async { bool foundCars = false; int attempt = 0; // Set up the periodic timer Timer? timer = Timer.periodic(const Duration(seconds: 4), (Timer t) async { // Attempt to get car location foundCars = await getCarsLocationByPassengerAndReloadMarker( carType, attempt * 2000); Log.print('foundCars: $foundCars'); if (foundCars) { // If cars are found, cancel the timer and exit the search t.cancel(); } else if (attempt >= 4) { // After 4 attempts, stop the search t.cancel(); // No cars found after 4 attempts // MyDialog().getDialog( // "No Car or Driver Found in your area.".tr, // "No Car or Driver Found in your area.".tr, // () { // Get.back(); // }, // ); if (!foundCars) { noCarString = true; dataCarsLocationByPassenger = 'failure'; } update(); } attempt++; // Increment attempt }); } void startCarLocationSearch(String carType) { int searchInterval = 5; // Interval in seconds Log.print('searchInterval: $searchInterval'); int boundIncreaseStep = 2500; // Initial bounds in meters Log.print('boundIncreaseStep: $boundIncreaseStep'); int maxAttempts = 3; // Maximum attempts to increase bounds int maxBoundIncreaseStep = 6000; // Maximum bounds increase step int attempt = 0; // Current attempt Log.print('initial attempt: $attempt'); Timer.periodic(Duration(seconds: searchInterval), (Timer timer) async { Log.print('Current attempt: $attempt'); // Log current attempt bool foundCars = false; if (attempt >= maxAttempts) { timer.cancel(); if (foundCars == false) { noCarString = true; // dataCarsLocationByPassenger = 'failure'; update(); } // return; } else if (reloadStartApp == true) { Log.print('reloadStartApp: $reloadStartApp'); foundCars = await getCarsLocationByPassengerAndReloadMarker( carType, boundIncreaseStep); Log.print('foundCars: $foundCars'); if (foundCars) { timer.cancel(); } else { attempt++; if (reloadCount >= 3 || tick > 18 || reloadCount > 15) { timer.cancel(); } Log.print( 'Incrementing attempt to: $attempt'); // Log incremented attempt if (boundIncreaseStep < maxBoundIncreaseStep) { boundIncreaseStep += 1500; // Increase bounds if (boundIncreaseStep > maxBoundIncreaseStep) { boundIncreaseStep = maxBoundIncreaseStep; // Ensure it does not exceed the maximum } Log.print( 'New boundIncreaseStep: $boundIncreaseStep'); // Log new bounds } } } }); } String getLocationArea(double latitude, double longitude) { if (latitude >= 29.918901 && latitude <= 30.198857 && longitude >= 31.215009 && longitude <= 31.532186) { box.write(BoxName.serverChosen, AppLink.seferCairoServer); return 'Cairo'; } else if (latitude >= 29.904975 && latitude <= 30.143372 && longitude >= 30.787030 && longitude <= 31.215009) { box.write(BoxName.serverChosen, AppLink.seferGizaServer); return 'Giza'; } else if (latitude >= 30.396286 && latitude <= 31.654458 && longitude >= 29.041139 && longitude <= 32.626259) { box.write(BoxName.serverChosen, AppLink.seferAlexandriaServer); return 'Alexandria'; } else { box.write(BoxName.serverChosen, AppLink.seferCairoServer); return 'Cairo'; } } Future getCarsLocationByPassengerAndReloadMarker( String carType, int boundIncreaseStep) async { // if (statusRide == 'wait') { carsLocationByPassenger = []; LatLngBounds bounds = calculateBounds(passengerLocation.latitude, passengerLocation.longitude, boundIncreaseStep.toDouble()); var res; // await getLocation(); switch (carType) { case 'Lady': res = await CRUD() .get(link: AppLink.getFemalDriverLocationByPassenger, payload: { 'southwestLat': bounds.southwest.latitude.toString(), 'southwestLon': bounds.southwest.longitude.toString(), 'northeastLat': bounds.northeast.latitude.toString(), 'northeastLon': bounds.northeast.longitude.toString(), }); break; case 'Comfort': res = await CRUD() .get(link: AppLink.getCarsLocationByPassengerComfort, payload: { 'southwestLat': bounds.southwest.latitude.toString(), 'southwestLon': bounds.southwest.longitude.toString(), 'northeastLat': bounds.northeast.latitude.toString(), 'northeastLon': bounds.northeast.longitude.toString(), }); break; case 'Speed': res = await CRUD() .get(link: AppLink.getCarsLocationByPassengerSpeed, payload: { 'southwestLat': bounds.southwest.latitude.toString(), 'southwestLon': bounds.southwest.longitude.toString(), 'northeastLat': bounds.northeast.latitude.toString(), 'northeastLon': bounds.northeast.longitude.toString(), }); break; case 'Scooter': res = await CRUD() .get(link: AppLink.getCarsLocationByPassengerDelivery, payload: { 'southwestLat': bounds.southwest.latitude.toString(), 'southwestLon': bounds.southwest.longitude.toString(), 'northeastLat': bounds.northeast.latitude.toString(), 'northeastLon': bounds.northeast.longitude.toString(), }); break; case 'Awfar Car': res = await CRUD() .get(link: AppLink.getCarsLocationByPassengerBalash, payload: { 'southwestLat': bounds.southwest.latitude.toString(), 'southwestLon': bounds.southwest.longitude.toString(), 'northeastLat': bounds.northeast.latitude.toString(), 'northeastLon': bounds.northeast.longitude.toString(), }); break; case 'Pink Bike': res = await CRUD() .get(link: AppLink.getCarsLocationByPassengerPinkBike, payload: { 'southwestLat': bounds.southwest.latitude.toString(), 'southwestLon': bounds.southwest.longitude.toString(), 'northeastLat': bounds.northeast.latitude.toString(), 'northeastLon': bounds.northeast.longitude.toString(), }); break; default: res = await CRUD() .get(link: AppLink.getCarsLocationByPassenger, payload: { 'southwestLat': bounds.southwest.latitude.toString(), 'southwestLon': bounds.southwest.longitude.toString(), 'northeastLat': bounds.northeast.latitude.toString(), 'northeastLon': bounds.northeast.longitude.toString(), }); } if (res == 'failure') { noCarString = true; // dataCarsLocationByPassenger = 'failure'; update(); return false; } else { noCarString = false; dataCarsLocationByPassenger = jsonDecode(res); Log.print( 'dataCarsLocationByPassenger:getCarsLocationByPassengerAndReloadMarker ${dataCarsLocationByPassenger}'); // Check if 'message' is present and not null if (dataCarsLocationByPassenger != null && dataCarsLocationByPassenger.isNotEmpty) { // Check if carsOrder is within bounds // if (carsOrder < dataCarsLocationByPassenger['message'].length) { // driverId = dataCarsLocationByPassenger['message'][carsOrder] // ['driver_id'] // .toString(); // gender = dataCarsLocationByPassenger['message'][carsOrder]['gender'] // .toString(); // driverToken = dataCarsLocationByPassenger['message'][carsOrder] // ['token'] // .toString(); // } else { print('carsOrder is in of bounds for message array'); // return false; // } } else { // Get.defaultDialog(title: 'No cars available '); print('No cars available or message is null'); return false; } carsLocationByPassenger.clear(); // Clear existing markers for (var i = 0; i < dataCarsLocationByPassenger['message'].length; i++) { var json = dataCarsLocationByPassenger['message'][i]; _updateOrCreateMarker( MarkerId(json['latitude']).toString(), LatLng( double.parse(json['latitude']), double.parse(json['longitude'])), double.parse(json['heading']), _getIconForCar(json), ); driversToken.add(json['token']); } // Add fake car markers _addFakeCarMarkers(passengerLocation, 1); update(); return true; } // } // return false; } final List> fakeCarData = []; void _addFakeCarMarkers(LatLng center, int count) { if (fakeCarData.isEmpty) { Random random = Random(); double radiusInKm = 2.5; // 3 km diameter, so 1.5 km radius for (int i = 0; i < count; i++) { // Generate a random angle and distance within the circle double angle = random.nextDouble() * 2 * pi; double distance = sqrt(random.nextDouble()) * radiusInKm; // Convert distance to latitude and longitude offsets double latOffset = (distance / 111.32); // 1 degree lat ≈ 111.32 km double lonOffset = (distance / (111.32 * cos(radians(center.latitude)))); // Calculate new position double lat = center.latitude + (latOffset * cos(angle)); double lon = center.longitude + (lonOffset * sin(angle)); double heading = random.nextDouble() * 360; fakeCarData.add({ 'id': 'fake_$i', 'latitude': lat, 'longitude': lon, 'heading': heading, 'gender': 'Male', // Randomize gender }); } } for (var carData in fakeCarData) { _updateOrCreateMarker( MarkerId(carData['id']).toString(), LatLng(carData['latitude'], carData['longitude']), carData['heading'], _getIconForCar(carData), ); } } BitmapDescriptor _getIconForCar(Map carData) { if (carData['model'].toString().contains('دراجة')) { return motoIcon; } else if (carData['gender'] == 'Female') { return ladyIcon; } else { return carIcon; } } void _updateOrCreateMarker(String markerId, LatLng newPosition, double newHeading, BitmapDescriptor icon) { Marker? existingMarker = markers.cast().firstWhere( (m) => m?.markerId == MarkerId(markerId), orElse: () => null, ); if (existingMarker == null) { markers.add(Marker( markerId: MarkerId(markerId), position: newPosition, rotation: newHeading, icon: icon, )); } else { double distance = _calculateDistance(existingMarker.position, newPosition); if (distance >= minMovementThreshold) { _smoothlyUpdateMarker(existingMarker, newPosition, newHeading, icon); } } } void _smoothlyUpdateMarker(Marker oldMarker, LatLng newPosition, double newHeading, BitmapDescriptor icon) { String markerId = oldMarker.markerId.value; LatLng startPosition = oldMarker.position; double startHeading = oldMarker.rotation ?? 0; _animationTimers[markerId]?.cancel(); _animationTimers[markerId] = Timer.periodic(Duration(milliseconds: updateIntervalMs), (timer) { double progress = timer.tick / (500 / updateIntervalMs); // 500ms total duration if (progress >= 1.0) { timer.cancel(); _animationTimers.remove(markerId); progress = 1.0; } LatLng intermediatePosition = LatLng( startPosition.latitude + (newPosition.latitude - startPosition.latitude) * progress, startPosition.longitude + (newPosition.longitude - startPosition.longitude) * progress); double intermediateHeading = startHeading + (newHeading - startHeading) * progress; markers.removeWhere((m) => m.markerId == oldMarker.markerId); markers.add(Marker( markerId: oldMarker.markerId, position: intermediatePosition, rotation: intermediateHeading, icon: icon, )); update(); }); } double _calculateDistance(LatLng start, LatLng end) { // Implement distance calculation (e.g., Haversine formula) // For simplicity, this is a placeholder. Replace with actual implementation. return 1000 * sqrt(pow(start.latitude - end.latitude, 2) + pow(start.longitude - end.longitude, 2)); } Future getTokenForParent() async { if (box.read(BoxName.sosPhonePassenger) == null) { Get.defaultDialog( title: 'Add SOS Phone'.tr, titleStyle: AppStyle.title, content: Form( key: sosFormKey, child: MyTextForm( controller: sosPhonePassengerProfile, label: 'insert sos phone'.tr, hint: 'insert sos phone'.tr, type: TextInputType.phone, ), ), confirm: MyElevatedButton( title: 'Add SOS Phone'.tr, onPressed: () async { if (sosFormKey.currentState!.validate()) { Get.back(); await CRUD().post( link: AppLink.updateprofile, payload: { 'id': box.read(BoxName.passengerID), 'sosPhone': sosPhonePassengerProfile.text, }, ); box.write( BoxName.sosPhonePassenger, sosPhonePassengerProfile.text); } })); } var res = await CRUD().getTokenParent( link: AppLink.getTokenParent, payload: {'phone': '+2${box.read(BoxName.sosPhonePassenger)}'}); // Check if `res` is already a map if (res is Map) { var res1 = res; handleResponse(res1); } else { // If it's a string, decode it var res1 = jsonDecode(res); handleResponse(res1); } } // Function to check if the point is inside the polygon bool isPointInPolygon(LatLng point, List polygon) { int intersections = 0; for (int i = 0; i < polygon.length; i++) { LatLng vertex1 = polygon[i]; LatLng vertex2 = polygon[(i + 1) % polygon.length]; // Loop back to the start if (_rayIntersectsSegment(point, vertex1, vertex2)) { intersections++; } } // If the number of intersections is odd, the point is inside return intersections % 2 != 0; } // Helper function to check if a ray from the point intersects with a polygon segment bool _rayIntersectsSegment(LatLng point, LatLng vertex1, LatLng vertex2) { double px = point.longitude; double py = point.latitude; double v1x = vertex1.longitude; double v1y = vertex1.latitude; double v2x = vertex2.longitude; double v2y = vertex2.latitude; // Check if the point is outside the vertical bounds of the segment if ((py < v1y && py < v2y) || (py > v1y && py > v2y)) { return false; } // Calculate the intersection of the ray and the segment double intersectX = v1x + (py - v1y) * (v2x - v1x) / (v2y - v1y); // Check if the intersection is to the right of the point return intersectX > px; } bool isInUniversity = false; // Function to check if the passenger is in any university polygon // Function to check if the passenger is in any university polygon and return the university name String checkPassengerLocation(LatLng passengerLocation, List> universityPolygons, List universityNames) { for (int i = 0; i < universityPolygons.length; i++) { if (isPointInPolygon(passengerLocation, universityPolygons[i])) { isInUniversity = true; return "Passenger is in ${universityNames[i]}"; } } return "Passenger is not in any university"; } String passengerLocationStringUnvirsity = 'unKnown'; void getPassengerLocationUniversity() { // Check if the passenger is inside any of the university polygons and get the university name passengerLocationStringUnvirsity = checkPassengerLocation( passengerLocation, UniversitiesPolygons.universityPolygons, UniversitiesPolygons.universityNames, ); if (passengerLocationStringUnvirsity != 'unKnown') { // Get.snackbar('you are in $passengerLocationStringUnvirsity', ""); } print(passengerLocationStringUnvirsity); } var polygons = {}.obs; // Initialize polygons from UniversitiesPolygons void _initializePolygons() { List> universityPolygons = UniversitiesPolygons.universityPolygons; List universityNames = UniversitiesPolygons.universityNames; for (int i = 0; i < universityPolygons.length; i++) { Polygon polygon = Polygon( polygonId: PolygonId(universityNames[i]), points: universityPolygons[i], strokeColor: Colors.blueAccent, fillColor: Colors.blueAccent.withOpacity(0.2), strokeWidth: 2, ); polygons.add(polygon); // Add polygon to observable set } } void handleResponse(Map res1) { if (res1['message'] == "No passenger found for the given phone number") { Get.defaultDialog( title: "No user found for the given phone number".tr, titleStyle: AppStyle.title, content: Column( children: [ Text( "No passenger found for the given phone number".tr, style: AppStyle.title, ), Text( "Send Sefer app to him".tr, style: AppStyle.title.copyWith(color: AppColor.greenColor), ) ], ), confirm: MyElevatedButton( title: 'Ok'.tr, onPressed: () { Get.back(); var phone = box.read(BoxName.countryCode) == 'Egypt' ? '+2${box.read(BoxName.sosPhonePassenger)}' : '+962${box.read(BoxName.sosPhonePassenger)}'; var message = '''Dear , 🚀 I have just started an exciting trip and I would like to share the details of my journey and my current location with you in real-time! Please download the SEFER app. It will allow you to view my trip details and my latest location. 👉 Download link: Android [https://play.google.com/store/apps/details?id=com.mobileapp.store.ride] iOS [https://getapp.cc/app/6458734951] I look forward to keeping you close during my adventure! SEFER ,''' .tr; launchCommunication('whatsapp', phone, message); }), cancel: MyElevatedButton( title: 'No'.tr, onPressed: () { Get.back(); })); } else if (res1['status'] == 'success') { var tokenParent = res1['data'][0]['token']; Get.snackbar("The invitation was sent successfully".tr, '', backgroundColor: AppColor.greenColor); FirebaseMessagesController().sendNotificationToPassengerToken( "Trip Monitoring".tr, "Trip Monitoring".tr, tokenParent, [rideId, driverId], 'order1.wav', ); box.write(BoxName.parentTripSelected, true); box.write(BoxName.tokenParent, tokenParent); } } LatLng driverLocationToPassenger = const LatLng(32, 35); Future getDriverCarsLocationToPassengerAfterApplied() async { driverCarsLocationToPassengerAfterApplied = []; var res = await CRUD().get( link: AppLink.getDriverCarsLocationToPassengerAfterApplied, payload: {'driver_id': driverId}); datadriverCarsLocationToPassengerAfterApplied = jsonDecode(res); driverLocationToPassenger = LatLng( double.parse(datadriverCarsLocationToPassengerAfterApplied['message'][0] ['latitude']), double.parse(datadriverCarsLocationToPassengerAfterApplied['message'][0] ['longitude'])); driverCarsLocationToPassengerAfterApplied.add(LatLng( double.parse(datadriverCarsLocationToPassengerAfterApplied['message'][0] ['latitude']), double.parse(datadriverCarsLocationToPassengerAfterApplied['message'][0] ['longitude']))); CarLocationModel model = CarLocationModel.fromJson( datadriverCarsLocationToPassengerAfterApplied['message'][0]); carLocationsModels.add(model); update(); } Future runEvery30SecondsUntilConditionMet() async { // Calculate the duration of the trip in minutes. double tripDurationInMinutes = durationToPassenger / 5; int loopCount = tripDurationInMinutes.ceil(); // If the trip duration is less than or equal to 50 minutes, then break the loop. for (var i = 0; i < loopCount; i++) { // Wait for 50 seconds. await Future.delayed(const Duration(seconds: 5)); if (rideTimerBegin == true || statusRide == 'Apply') { await getDriverCarsLocationToPassengerAfterApplied(); reloadMarkerDriverCarsLocationToPassengerAfterApplied(); } } } Future runWhenRideIsBegin() async { // Calculate the duration of the trip in minutes. double tripDurationInMinutes = durationToRide / 6; int loopCount = tripDurationInMinutes.ceil(); // If the trip duration is less than or equal to 50 minutes, then break the loop. clearMarkersExceptStartEnd(); for (var i = 0; i < loopCount; i++) { // Wait for 50 seconds. await Future.delayed(const Duration(seconds: 4)); // if (rideTimerBegin == true && statusRide == 'Apply') { await getDriverCarsLocationToPassengerAfterApplied(); // } reloadMarkerDriverCarsLocationToPassengerAfterApplied(); } } Timer? _timer; // final int updateIntervalMs = 100; // Update every 100ms // final double minMovementThreshold = // 1.0; // Minimum movement in meters to trigger update void clearMarkersExceptStartEnd() { Set markersToRemove = markers .where((marker) => marker.markerId != const MarkerId("start") && marker.markerId != const MarkerId("end")) .toSet(); for (Marker marker in markersToRemove) { markers.remove(marker); } update(); } void reloadMarkerDriverCarsLocationToPassengerAfterApplied() { // clearMarkersExceptStartEnd(); LatLng driverPosition = LatLng( double.parse(datadriverCarsLocationToPassengerAfterApplied['message'][0] ['latitude']), double.parse(datadriverCarsLocationToPassengerAfterApplied['message'][0] ['longitude'])); double heading = double.parse( datadriverCarsLocationToPassengerAfterApplied['message'][0]['heading'] .toString()); BitmapDescriptor icon = datadriverCarsLocationToPassengerAfterApplied['message'][0] ['model'] .toString() .contains('دراجة') || datadriverCarsLocationToPassengerAfterApplied['message'][0] ['make'] .toString() .contains('دراجة') ? motoIcon : datadriverCarsLocationToPassengerAfterApplied['message'][0] ['gender'] == 'Female' ? ladyIcon : carIcon; _updateMarkerPosition(driverPosition, heading, icon); } void _updateMarkerPosition( LatLng newPosition, double newHeading, BitmapDescriptor icon) { const String markerId = 'driverToPassengers'; Marker? existingMarker = markers.cast().firstWhere( (m) => m?.markerId == const MarkerId(markerId), orElse: () => null, ); if (existingMarker == null) { // If the marker doesn't exist, create it at the new position markers.add(Marker( markerId: const MarkerId(markerId), position: newPosition, rotation: newHeading, icon: icon, )); update(); } else { // If the marker exists, check if the movement is significant enough to update double distance = _calculateDistance(existingMarker.position, newPosition); if (distance >= minMovementThreshold) { _smoothlyUpdateMarker(existingMarker, newPosition, newHeading, icon); } } mapController?.animateCamera(CameraUpdate.newLatLng(newPosition)); } @override void onClose() { _timer?.cancel(); _animationTimers.forEach((_, timer) => timer.cancel()); _animationTimers.clear(); super.onClose(); } restCounter() { clearPlacesDestination(); clearPolyline(); data = []; rideConfirm = false; shouldFetch = false; timeToPassengerFromDriverAfterApplied = 0; update(); } Future cancelRideAfterRejectFromAll() async { clearPlacesDestination(); clearPolyline(); data = []; await CRUD().post(link: AppLink.updateRides, payload: { "id": rideId.toString(), // Convert to String "status": 'notApplyFromAnyDriver' }); if (AppLink.endPoint != AppLink.seferCairoServer) { CRUD().post(link: "${AppLink.endPoint}/ride/rides/update.php", payload: { "id": rideId.toString(), // Convert to String "status": 'notApplyFromAnyDriver' }); } rideConfirm = false; statusRide == 'Cancel'; isSearchingWindow = false; shouldFetch = false; isPassengerChosen = false; isCashConfirmPageShown = false; // totalStepDurations = 0; isCashSelectedBeforeConfirmRide = false; timeToPassengerFromDriverAfterApplied = 0; changeCancelRidePageShow(); remainingTime = 0; update(); } Future cancelRide() async { // if (rideConfirm == true || // statusRide == 'Apply' || // statusRide == 'Applied' || // statusRide == 'wait' || // statusRide == 'waiting') { clearPlacesDestination(); clearPolyline(); // clearPolylineAll(); data = []; changeCancelRidePageShow(); if (rideId != 'yet') { Log.print('cancelRide: 1'); FirebaseMessagesController().sendNotificationToDriverMAP( 'Cancel Trip'.tr, 'Trip Cancelled'.tr, driverToken.toString(), [], 'cancel.wav', ); await Future.wait([ CRUD().post(link: AppLink.updateRides, payload: { "id": rideId.toString(), // Convert to String "status": 'Cancel' }), CRUD().post(link: AppLink.updateDriverOrder, payload: { "order_id": rideId.toString(), // Convert to String "status": 'Cancel' }), CRUD().post(link: AppLink.updateWaitingTrip, payload: { "id": rideId.toString(), // Convert to String "status": 'Cancel' }), ]); if (AppLink.endPoint != AppLink.seferCairoServer) { CRUD().post( link: "${AppLink.endPoint}/ride/driver_order/update.php", payload: { "order_id": rideId.toString(), // Convert to String "status": 'Cancel' }); CRUD() .post(link: "${AppLink.endPoint}/ride/rides/update.php", payload: { "id": rideId.toString(), // Convert to String "status": 'Cancel' }); CRUD().post( link: "${AppLink.endPoint}/ride/notificationCaptain/updateWaitingTrip.php", payload: { "id": rideId.toString(), // Convert to String "status": 'Cancel' }); } print('Cancel'); // } } Future.delayed(const Duration(seconds: 1)); Get.offAll(() => const MapPagePassenger()); } void changePickerShown() { isPickerShown = !isPickerShown; heightPickerContainer = isPickerShown == true ? 150 : 90; update(); } void changeHeightPointsPageForRider() { isPointsPageForRider = !isPointsPageForRider; heightPointsPageForRider = isPointsPageForRider == true ? Get.height : 0; update(); } getCoordinateFromMapWayPoints(int index) { placesCoordinate[index] = newStartPointLocation.toString(); update(); } void changeMainBottomMenuMap() { if (isWayPointStopsSheetUtilGetMap == true) { changeWayPointSheet(); } else { isMainBottomMenuMap = !isMainBottomMenuMap; mainBottomMenuMapHeight = isMainBottomMenuMap == true ? Get.height * .2 : Get.height * .55; isWayPointSheet = false; if (heightMenuBool == true) { getDrawerMenu(); } initilizeGetStorage(); update(); } } void downPoints() { if (Get.find().wayPoints.length < 2) { isWayPointStopsSheetUtilGetMap = false; isWayPointSheet = false; wayPointSheetHeight = isWayPointStopsSheet ? Get.height * .45 : 0; // changeWayPointStopsSheet(); update(); } // changeWayPointStopsSheet(); // isWayPointSheet = false; update(); } void changeWayPointSheet() { isWayPointSheet = !isWayPointSheet; wayPointSheetHeight = isWayPointSheet == false ? 0 : Get.height * .45; // if (heightMenuBool == true) { // getDrawerMenu(); // } update(); } void changeWayPointStopsSheet() { // int waypointsLength = Get.find().wayPoints.length; if (wayPointIndex > -1) { isWayPointStopsSheet = true; isWayPointStopsSheetUtilGetMap = true; } isWayPointStopsSheet = !isWayPointStopsSheet; wayPointSheetHeight = isWayPointStopsSheet ? Get.height * .45 : 0; // if (heightMenuBool == true) { // getDrawerMenu(); // } update(); } changeHeightPlaces() { if (placesDestination.isEmpty) { height = 0; update(); } height = 150; update(); } changeHeightStartPlaces() { if (placesStart.isEmpty) { height = 0; update(); } height = 150; update(); } changeHeightPlacesAll(int index) { if (placeListResponseAll[index].isEmpty) { height = 0; update(); } height = 150; update(); } changeHeightPlaces1() { if (wayPoint1.isEmpty) { height = 0; update(); } height = 150; update(); } changeHeightPlaces2() { if (wayPoint2.isEmpty) { height = 0; update(); } height = 150; update(); } changeHeightPlaces3() { if (wayPoint3.isEmpty) { height = 0; update(); } height = 150; update(); } changeHeightPlaces4() { if (wayPoint4.isEmpty) { height = 0; update(); } height = 150; update(); } hidePlaces() { height = 0; update(); } // Future getPlaces() async { // var languageCode; // // Check if `placeDestinationController.text` contains English characters // if (RegExp(r'[a-zA-Z]').hasMatch(placeDestinationController.text)) { // languageCode = 'en'; // } else { // languageCode = 'ar'; // } // var url = // '${AppLink.searcMaps}?q=${placeDestinationController.text}&in=circle:${passengerLocation.latitude},${passengerLocation.longitude};r=250000&countryCode=${box.read(BoxName.countryCode) == 'EGYPT' ? 'EGY' : 'JOR'}&apiKey=${AK.apiKeyHere}'; // // '${AppLink.googleMapsLink}place/nearbysearch/json?location=${mylocation.longitude}&radius=25000&language=ar&keyword=&key=${placeController.text}${AK.mapAPIKEY}'; // // '${AppLink.googleMapsLink}place/nearbysearch/json?keyword=${placeDestinationController.text}&location=${passengerLocation.latitude},${passengerLocation.longitude}&radius=250000&language=$languageCode&key=${AK.mapAPIKEY.toString()}'; // print(url); // var response = await CRUD().getGoogleApi(link: url, payload: {}); // Log.print('response: ${response}'); // placesDestination = response['results']; // update(); // } getAIKey(String key) async { var res = await CRUD().get(link: AppLink.getapiKey, payload: {"keyName": key}); if (res != 'failure') { var d = jsonDecode(res)['message']; return d[key].toString(); } else {} } Future getPlaces() async { var languageCode; // Check if `placeDestinationController.text` contains English characters if (RegExp(r'[a-zA-Z]').hasMatch(placeDestinationController.text)) { languageCode = 'en'; } else { languageCode = 'ar'; } // Construct the URL var url = Uri.parse( '${AppLink.searcMaps}?q=${Uri.encodeQueryComponent(placeDestinationController.text)}&limit=4&in=circle:${passengerLocation.latitude},${passengerLocation.longitude};r=250000&countryCode=${box.read(BoxName.countryCode) == 'EGYPT' ? 'EGY' : 'JOR'}&lang=$languageCode&apiKey=$k', ); // Log the URL for debugging print(url); // box.remove(BoxName.placesDestination); try { // Make the API request var response = await CRUD().getHereMap( link: url.toString(), ); // Log the response for debugging // Log.print('response: ${response}'); // Check if the response is valid if (response != null && response['items'] != null) { placesDestination = response['items']; // Log.print('placesDestination: ${placesDestination}'); placesDestination = response['items']; // box.write(BoxName.placesDestination, placesDestination); for (var i = 0; i < placesDestination.length; i++) { var res = placesDestination[i]; // Extract fields with null safety var title = res['title']?.toString() ?? 'Unknown Place'; var position = res['position']; var address = res['address']?['label'] ?? 'Unknown Address'; if (position == null) { Log.print('Position is null for place: $title'); continue; // Skip this place and continue with the next one } String latitude = position['lat']?.toString() ?? '0.0'; String longitude = position['lng']?.toString() ?? '0.0'; try { await savePlaceToServer(latitude, longitude, title, address); // Log.print('Place saved successfully: $title'); } catch (e) { // Log.print('Failed to save place: $e'); } } // todo save key in env then get key and use it } else { placesDestination = []; } } catch (e) { // Handle any errors that occur during the API request Log.print('Error fetching places: $e'); placesDestination = []; } // Notify listeners that the state has changed update(); } Future getPlacesStart() async { var languageCode = wayPoint0Controller.text; // Regular expression to check for English alphabet characters final englishRegex = RegExp(r'[a-zA-Z]'); // Check if text contains English characters if (englishRegex.hasMatch(languageCode)) { languageCode = 'en'; } else { languageCode = 'ar'; } var url = // '${AppLink.googleMapsLink}place/nearbysearch/json?location=${mylocation.longitude}&radius=25000&language=ar&keyword=&key=${placeController.text}${AK.mapAPIKEY}'; '${AppLink.googleMapsLink}place/nearbysearch/json?keyword=${placeStartController.text}&location=${passengerLocation.latitude},${passengerLocation.longitude}&radius=250000&language=$languageCode&key=${AK.mapAPIKEY.toString()}'; var response = await CRUD().getGoogleApi(link: url, payload: {}); placesStart = response['results']; update(); } Future getPlacesListsWayPoint(int index) async { var languageCode = wayPoint0Controller.text; // Regular expression to check for English alphabet characters final englishRegex = RegExp(r'[a-zA-Z]'); // Check if text contains English characters if (englishRegex.hasMatch(languageCode)) { languageCode = 'en'; } else { languageCode = 'ar'; } var url = '${AppLink.googleMapsLink}place/nearbysearch/json?keyword=${wayPoint0Controller.text}&location=${passengerLocation.latitude},${passengerLocation.longitude}&radius=250000&language=$languageCode&key=${AK.mapAPIKEY.toString()}'; try { var response = await CRUD().getGoogleApi(link: url, payload: {}); if (response != null && response['results'] != null) { wayPoint0 = response['results']; placeListResponseAll[index] = response['results']; update(); } else { print('Error: Invalid response from Google Places API'); } } catch (e) { print('Error fetching places: $e'); } } Future savePlaceToServer( String latitude, String longitude, String name, String rate) async { var data = { 'latitude': latitude, 'longitude': longitude, 'name': name, 'rate': rate, }; try { CRUD().post( link: AppLink.savePlacesServer, payload: data, ); } catch (e) { print('Error: $e'); } } // Future getPlacesListsWayPoint(int index) async { // var url = // '${AppLink.googleMapsLink}place/nearbysearch/json?keyword=${wayPoint0Controller.text}&location=${passengerLocation.latitude},${passengerLocation.longitude}&radius=80000&language=${}&key=${AK.mapAPIKEY.toString()}'; // var response = await CRUD().getGoogleApi(link: url, payload: {}); // wayPoint0 = response['results']; // placeListResponseAll[index] = response['results']; // update(); // } LatLng fromString(String location) { List parts = location.split(','); double lat = double.parse(parts[0]); double lng = double.parse(parts[1]); return LatLng(lat, lng); } void clearPolyline() { polyLines = []; polylineCoordinates.clear(); // polylineCoordinates = []; polylineCoordinatesPointsAll[0].clear(); polylineCoordinatesPointsAll[1].clear(); polylineCoordinatesPointsAll[2].clear(); polylineCoordinatesPointsAll[3].clear(); polylineCoordinatesPointsAll[4].clear(); isMarkersShown = false; update(); } void addCustomPicker() { ImageConfiguration config = ImageConfiguration( size: const Size(30, 30), devicePixelRatio: Get.pixelRatio // scale: 1.0, ); BitmapDescriptor.asset( config, 'assets/images/picker.png', // mipmaps: false, ).then((value) { markerIcon = value; update(); }); } void addCustomStartIcon() async { // Create the marker with the resized image ImageConfiguration config = ImageConfiguration( size: const Size(30, 30), devicePixelRatio: Get.pixelRatio); BitmapDescriptor.asset( config, 'assets/images/A.png', // mipmaps: false, ).then((value) { startIcon = value; update(); }); } void addCustomEndIcon() { ImageConfiguration config = ImageConfiguration( size: const Size(30, 30), devicePixelRatio: Get.pixelRatio); BitmapDescriptor.asset( config, 'assets/images/b.png', // mipmaps: false, ).then((value) { endIcon = value; update(); }); } void addCustomCarIcon() { ImageConfiguration config = ImageConfiguration( size: const Size(30, 35), devicePixelRatio: Get.pixelRatio); BitmapDescriptor.asset( config, 'assets/images/car.png', // mipmaps: false, ).then((value) { carIcon = value; update(); }); } void addCustomMotoIcon() { ImageConfiguration config = ImageConfiguration( size: const Size(30, 30), devicePixelRatio: Get.pixelRatio); BitmapDescriptor.asset( config, 'assets/images/moto1.png', // mipmaps: false, ).then((value) { motoIcon = value; update(); }); } void addCustomLadyIcon() { ImageConfiguration config = ImageConfiguration( size: const Size(30, 30), devicePixelRatio: Get.pixelRatio); BitmapDescriptor.asset( config, 'assets/images/lady1.png', // mipmaps: false, ).then((value) { ladyIcon = value; update(); }); } void addCustomStepIcon() { ImageConfiguration config = ImageConfiguration( size: const Size(30, 30), devicePixelRatio: Get.pixelRatio); BitmapDescriptor.asset( config, 'assets/images/brand.png', // mipmaps: false, ).then((value) { tripIcon = value; update(); }); } dialoge() { Get.defaultDialog( title: 'Location '.tr, content: Container( child: Column( children: [ Text( 'We use location to get accurate and nearest driver for you'.tr, style: AppStyle.title, ), TextButton( onPressed: () async { // await Permission.location.request(); Get.back(); }, child: Text( 'Grant'.tr, style: AppStyle.title, ), ) ], ), ), ); } double speed = 0; Future getLocation() async { isLoading = true; update(); bool serviceEnabled; PermissionStatus permissionGranted; // dialoge(); // Check if location services are enabled serviceEnabled = await location.serviceEnabled(); if (!serviceEnabled) { serviceEnabled = await location.requestService(); if (!serviceEnabled) { // Location services are still not enabled, handle the error return; } } // Check if the app has permission to access location permissionGranted = await location.hasPermission(); if (permissionGranted == PermissionStatus.denied) { permissionGranted = await location.requestPermission(); if (permissionGranted != PermissionStatus.granted) { // Location permission is still not granted, handle the error return; } } // Configure location accuracy // LocationAccuracy desiredAccuracy = LocationAccuracy.high; // Get the current location LocationData _locationData = await location.getLocation(); passengerLocation = (_locationData.latitude != null && _locationData.longitude != null ? LatLng(_locationData.latitude!, _locationData.longitude!) : null)!; getLocationArea(passengerLocation.latitude, passengerLocation.longitude); Log.print('AppLink.endPoint: ${AppLink.endPoint}'); // Log.print('BoxName.serverChosen: ${box.read(BoxName.serverChosen)}'); newStartPointLocation = passengerLocation; Log.print('passengerLocation: $passengerLocation'); speed = _locationData.speed!; // //print location details isLoading = false; update(); } // LatLngBounds calculateBounds(double 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 lngDelta = (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(minLat, minLng), northeast: LatLng(maxLat, maxLng), ); } GoogleMapController? mapController; void onMapCreated(GoogleMapController controller) { // myLocation = Get.find().location as LatLng; // myLocation = myLocation; mapController = controller; controller.getVisibleRegion(); controller.animateCamera( CameraUpdate.newLatLng(passengerLocation), ); update(); } // void startMarkerReloading() { // int count = 0; // markerReloadingTimer = Timer.periodic(const Duration(seconds: 30), (timer) { // reloadMarkers(); // // count++; // if (count == 10) { // timer.cancel(); // } // }); // } bool reloadStartApp = false; int reloadCount = 0; startMarkerReloading() async { if (reloadStartApp == false) { Timer.periodic(const Duration(seconds: 3), (timer) async { reloadCount++; Log.print('reloadCount: $reloadCount'); if (rideConfirm == false) { clearMarkersExceptStartEnd(); // _smoothlyUpdateMarker(); // startCarLocationSearch(box.read(BoxName.carType)); await getCarsLocationByPassengerAndReloadMarker( box.read(BoxName.carType), 5000); await getNearestDriverByPassengerLocation(); Log.print('reloadMarkers: from startMarkerReloading'); } else { // runWhenRideIsBegin(); } if (reloadCount >= 6) { reloadStartApp = true; timer.cancel(); // Stop the timer after 5 reloads } }); } } String durationByPassenger = ''; late DateTime newTime1 = DateTime.now(); late DateTime timeFromDriverToPassenger = DateTime.now(); String distanceByPassenger = ''; late Duration durationFromDriverToPassenger; double nearestDistance = double.infinity; // Future getNearestDriverByPassengerLocation() async { // if (polyLines.isEmpty || data.isEmpty) { // return null; // Early return if data is empty // } // if (!rideConfirm) { // if (dataCarsLocationByPassenger != 'failure') { // if (dataCarsLocationByPassenger != null) { // if (dataCarsLocationByPassenger['message'].length > 0) { // double nearestDistance = double // .infinity; // Initialize nearest distance to a large number // CarLocation? nearestCar; // for (var i = 0; // i < dataCarsLocationByPassenger['message'].length; // i++) { // var carLocation = dataCarsLocationByPassenger['message'][i]; // // Calculate the distance between passenger's location and current driver's location // final distance = Geolocator.distanceBetween( // passengerLocation.latitude, // passengerLocation.longitude, // double.parse(carLocation['latitude']), // double.parse(carLocation['longitude']), // ); // // Calculate duration assuming an average speed of 25 km/h (adjust as needed) // int durationToPassenger = // (distance * 25 * (1000 / 3600)).round(); // 25 km/h in m/s // // Update the UI with the distance and duration for each car // update(); // // If this distance is smaller than the nearest distance found so far, update nearestCar // if (distance < nearestDistance) { // nearestDistance = distance; // nearestCar = CarLocation( // distance: distance, // duration: durationToPassenger.toDouble(), // id: carLocation['driver_id'], // latitude: double.parse(carLocation['latitude']), // longitude: double.parse(carLocation['longitude']), // ); // // Update the UI with the nearest driver // update(); // } // } // // Return the nearest car found // return nearestCar; // } // } // } // } // // Return null if no drivers are found or if ride is confirmed // return null; // } Future getNearestDriverByPassengerLocation() async { if (!rideConfirm) { if (dataCarsLocationByPassenger != 'failure' && dataCarsLocationByPassenger != null && dataCarsLocationByPassenger['message'] != null && dataCarsLocationByPassenger['message'].length > 0) { double nearestDistance = double.infinity; // Initialize nearest distance CarLocation? nearestCar; for (var i = 0; i < dataCarsLocationByPassenger['message'].length; i++) { var carLocation = dataCarsLocationByPassenger['message'][i]; Log.print('carLocation: $carLocation'); try { // Calculate distance between passenger's location and current driver's location final distance = Geolocator.distanceBetween( passengerLocation.latitude, passengerLocation.longitude, double.parse(carLocation['latitude']), double.parse(carLocation['longitude']), ); // Calculate duration assuming an average speed of 25 km/h (adjust as needed) int durationToPassenger = (distance / 1000 / 25 * 3600).round(); Log.print('distance: $distance'); Log.print('durationToPassenger: $durationToPassenger'); Log.print('passengerLocation: $passengerLocation'); Log.print('carLocation: $carLocation'); Log.print('distance: $distance meters'); Log.print('durationToPassenger: $durationToPassenger seconds'); // Update the UI with the distance and duration for each car update(); // If this distance is smaller than the nearest distance found so far, update nearestCar if (distance < nearestDistance) { nearestDistance = distance; nearestCar = CarLocation( distance: distance, duration: durationToPassenger.toDouble(), id: carLocation['driver_id'], latitude: double.parse(carLocation['latitude']), longitude: double.parse(carLocation['longitude']), ); Log.print('nearestCar: $nearestCar'); // Update the UI with the nearest driver update(); } } catch (e) { Log.print('Error calculating distance/duration: $e'); } } // Return the nearest car found return nearestCar; } } // Return null if no drivers are found or if ride is confirmed return null; } getNearestDriverByPassengerLocationAPIGOOGLE() async { if (polyLines.isEmpty || data.isEmpty) { return null; // Early return if data is empty } if (!rideConfirm) { double nearestDistance = double.infinity; if (dataCarsLocationByPassenger != 'failure') { if (dataCarsLocationByPassenger['message'].length > 0) { for (var i = 0; i < dataCarsLocationByPassenger['message'].length; i++) { var carLocation = dataCarsLocationByPassenger['message'][i]; // } // isloading = true; update(); // Make API request to get exact distance and duration String apiUrl = '${AppLink.googleMapsLink}distancematrix/json?destinations=${carLocation['latitude']},${carLocation['longitude']}&origins=${passengerLocation.latitude},${passengerLocation.longitude}&units=metric&key=${AK.mapAPIKEY}'; var response = await CRUD().getGoogleApi(link: apiUrl, payload: {}); if (response != null && response['status'] == "OK") { var data = response; // Extract distance and duration from the response and handle accordingly int distance1 = data['rows'][0]['elements'][0]['distance']['value']; distanceByPassenger = data['rows'][0]['elements'][0]['distance']['text']; durationToPassenger = data['rows'][0]['elements'][0]['duration']['value']; durationFromDriverToPassenger = Duration(seconds: durationToPassenger.toInt()); newTime1 = currentTime.add(durationFromDriverToPassenger); timeFromDriverToPassenger = newTime1.add(Duration(minutes: 2.toInt())); durationByPassenger = data['rows'][0]['elements'][0]['duration']['text']; update(); if (distance1 < nearestDistance) { nearestDistance = distance1.toDouble(); nearestCar = CarLocation( distance: distance1.toDouble(), duration: durationToPassenger.toDouble(), id: carLocation['driver_id'], latitude: double.parse(carLocation['latitude']), longitude: double.parse(carLocation['longitude']), ); // isloading = false; update(); } } // Handle the distance and duration as needed else { // 'Failed to retrieve distance and duration: ${response['status']}'); Log.print('${response['status']}: ${response['status']}}'); // Handle the failure case } } } } } } calculateDistanceBetweenPassengerAndDriverBeforeCancelRide() async { await getDriverCarsLocationToPassengerAfterApplied(); double distance = Geolocator.distanceBetween( passengerLocation.latitude, passengerLocation.longitude, driverCarsLocationToPassengerAfterApplied.last.latitude, driverCarsLocationToPassengerAfterApplied.last.longitude, ); if (distance > 500) { isCancelRidePageShown = true; update(); } else { Get.defaultDialog( barrierDismissible: false, title: 'The Driver Will be in your location soon .'.tr, middleText: 'The distance less than 500 meter.'.tr, confirm: Column( children: [ MyElevatedButton( kolor: AppColor.greenColor, title: 'Ok'.tr, onPressed: () { Get.back(); }, ), MyElevatedButton( kolor: AppColor.redColor, title: 'No, I want to cancel this trip'.tr, onPressed: () { Get.back(); MyDialog().getDialog( 'Attention'.tr, 'You will be charged for the cost of the driver coming to your location.' .tr, () async { Get.back(); Get.find() .payToDriverForCancelAfterAppliedAndHeNearYou(rideId); // isCancelRidePageShown = true; // update(); }, ); }, ), ], ), ); // cancel: MyElevatedButton( // title: 'No.Iwant Cancel Trip.'.tr, onPressed: () {})); } } List headingAngles = []; double calculateAngleBetweenLocations(LatLng start, LatLng end) { double startLat = start.latitude * math.pi / 180; double startLon = start.longitude * math.pi / 180; double endLat = end.latitude * math.pi / 180; double endLon = end.longitude * math.pi / 180; double dLon = endLon - startLon; double y = math.sin(dLon) * cos(endLat); double x = cos(startLat) * math.sin(endLat) - math.sin(startLat) * cos(endLat) * cos(dLon); double angle = math.atan2(y, x); double angleDegrees = angle * 180 / math.pi; return angleDegrees; } late LatLngBounds boundsData; late String startNameAddress = ''; late String endNameAddress = ''; getMap(String origin, destination) async { isLoading = true; update(); remainingTime = 25; //to make cancel every call // startCarLocationSearch(box.read(BoxName.carType)); await getCarsLocationByPassengerAndReloadMarker( box.read(BoxName.carType), 5000); // await getCarsLocationByPassengerAndReloadMarker(); var coordDestination = destination.split(','); double latPassengerDestination = double.parse(coordDestination[0]); double lngPassengerDestination = double.parse(coordDestination[1]); myDestination = LatLng(latPassengerDestination, lngPassengerDestination); if (origin.isEmpty) { origin = '${passengerLocation.latitude.toString().split(',')[0]},${passengerLocation.longitude.toString().split(',')[1]}'; //todo } isLoading = false; update(); var url = ('${AppLink.googleMapsLink}directions/json?&language=${box.read(BoxName.lang) ?? 'ar'}&avoid=tolls|ferries&destination=$destination&origin=$origin&key=${AK.mapAPIKEY}'); var response = await CRUD().getGoogleApi(link: url, payload: {}); data = response['routes'][0]['legs']; box.remove(BoxName.tripData); box.write(BoxName.tripData, response); startNameAddress = shortenAddress(data[0]['start_address']); print('data[0][start_address]: ${data[0]['start_address']}'); endNameAddress = shortenAddress(data[0]['end_address']); isLoading = false; newStartPointLocation = LatLng( data[0]["start_location"]['lat'], data[0]["start_location"]['lng']); markers.add( Marker( markerId: const MarkerId('start'), position: newStartPointLocation, icon: startIcon, ), ); markers.add( Marker( markerId: const MarkerId('end'), position: LatLng( data[0]["end_location"]['lat'], data[0]["end_location"]['lng']), icon: endIcon, ), ); update(); durationToRide = data[0]['duration']['value']; final points = decodePolyline(response["routes"][0]["overview_polyline"]["points"]); for (int i = 0; i < points.length; i++) { double lat = points[i][0].toDouble(); double lng = points[i][1].toDouble(); polylineCoordinates.add(LatLng(lat, lng)); } // Define the northeast and southwest coordinates // Define the northeast and southwest coordinates final bounds = response["routes"][0]["bounds"]; LatLng northeast = LatLng(bounds['northeast']['lat'], bounds['northeast']['lng']); LatLng southwest = LatLng(bounds['southwest']['lat'], bounds['southwest']['lng']); // Create the LatLngBounds object LatLngBounds boundsData = LatLngBounds(northeast: northeast, southwest: southwest); // Fit the camera to the bounds var cameraUpdate = CameraUpdate.newLatLngBounds(boundsData, 160); mapController!.animateCamera(cameraUpdate); // getDistanceFromText(data[0]['distance']['text']); double distanceOfTrip = (data[0]['distance']['value']) / 1000; distance = distanceOfTrip; // updateCameraForDistanceAfterGetMap(); if (polyLines.isNotEmpty) { clearPolyline(); } else { var polyline = Polyline( polylineId: PolylineId(response["routes"][0]["summary"]), points: polylineCoordinates, width: 10, color: Colors.blue, ); polyLines.add(polyline); rideConfirm = false; isMarkersShown = true; update(); } } String shortenAddress(String fullAddress) { // Split the address into parts List parts = fullAddress.split('،'); // Remove any leading or trailing whitespace from each part parts = parts.map((part) => part.trim()).toList(); // Remove any empty parts parts = parts.where((part) => part.isNotEmpty).toList(); // Initialize the short address String shortAddress = ''; if (parts.isNotEmpty) { // Add the first part (usually the most specific location) shortAddress += parts[0]; } if (parts.length > 2) { // Add the district or area name (usually the third part in Arabic format) shortAddress += '، ${parts[2]}'; } else if (parts.length > 1) { // Add the second part for English or shorter addresses shortAddress += '، ${parts[1]}'; } // Add the country (usually the last part) if (parts.length > 1) { shortAddress += '، ${parts.last}'; } // Remove any part that's just numbers (like postal codes) shortAddress = shortAddress .split('،') .where((part) => !RegExp(r'^[0-9 ]+$').hasMatch(part.trim())) .join('،'); // Check if the address is in English bool isEnglish = RegExp(r'^[a-zA-Z0-9 ]+$').hasMatch(shortAddress.replaceAll('،', '')); if (isEnglish) { // Further processing for English addresses List englishParts = shortAddress.split('،'); if (englishParts.length > 2) { shortAddress = '${englishParts[0]}، ${englishParts[1]}، ${englishParts.last}'; } else if (englishParts.length > 1) { shortAddress = '${englishParts[0]}، ${englishParts.last}'; } } return shortAddress; } double distanceOfDestination = 0; bool haveSteps = false; late LatLng latestPosition; // getMapPoints(String originSteps, String destinationSteps, int index) async { // isWayPointStopsSheetUtilGetMap = false; // haveSteps = true; // await getCarsLocationByPassenger(); // // isLoading = true; // update(); // String url = '${AppLink.googleMapsLink}directions/json' // '?origin=${coordinatesWithoutEmpty.first}' // '&destination=${coordinatesWithoutEmpty.last}'; // if (coordinatesWithoutEmpty.length > 2) { // String waypoints = ""; // for (int i = 1; i < coordinatesWithoutEmpty.length - 1; i++) { // waypoints += "${coordinatesWithoutEmpty[i]}|"; // } // waypoints = waypoints.substring(0, waypoints.length - 1); // url += "&waypoints=$waypoints"; // } // url += '&language=en' // '&avoid=tolls|ferries' // '&key=${AK.mapAPIKEY}'; // var response = await CRUD().getGoogleApi(link: url, payload: {}); // data = response['routes'][0]['legs']; // // isLoading = false; // int durationToRide0 = data[0]['duration']['value']; // durationToRide = durationToRide + durationToRide0; // distance = distanceOfDestnation + (data[0]['distance']['value']) / 1000; // update(); // final points = // decodePolyline(response["routes"][0]["overview_polyline"]["points"]); // for (int i = 0; i < points.length; i++) { // if (points[i][0].toString() != '') { // double lat = points[i][0].toDouble(); // double lng = points[i][1].toDouble(); // polylineCoordinatesPointsAll[index].add(LatLng(lat, lng)); // } // } // // Define the northeast and southwest coordinates // update(); // if (polyLines.isNotEmpty) { // // clearPolyline(); // } else { // var polyline = Polyline( // polylineId: PolylineId(response["routes"][0]["summary"]), // points: polylineCoordinatesPointsAll[index], // width: 10, // color: Colors.blue, // ); // polyLines.add(polyline); // rideConfirm = false; // // isMarkersShown = true; // update(); // } // } getMapPoints(String originSteps, String destinationSteps, int index) async { isWayPointStopsSheetUtilGetMap = false; // haveSteps = true; // startCarLocationSearch(box.read(BoxName.carType)); await getCarsLocationByPassengerAndReloadMarker( box.read(BoxName.carType), 7000); // await getCarsLocationByPassengerAndReloadMarker(); // isLoading = true; update(); var url = ('${AppLink.googleMapsLink}directions/json?&language=${box.read(BoxName.lang)}&avoid=tolls|ferries&destination=$destinationSteps&origin=$originSteps&key=${AK.mapAPIKEY}'); var response = await CRUD().getGoogleApi(link: url, payload: {}); data = response['routes'][0]['legs']; // isLoading = false; int durationToRide0 = data[0]['duration']['value']; durationToRide = durationToRide + durationToRide0; distance = distanceOfDestination + (data[0]['distance']['value']) / 1000; update(); final points = decodePolyline(response["routes"][0]["overview_polyline"]["points"]); for (int i = 0; i < points.length; i++) { if (points[i][0].toString() != '') { double lat = points[i][0].toDouble(); double lng = points[i][1].toDouble(); polylineCoordinatesPointsAll[index].add(LatLng(lat, lng)); } } // Define the northeast and southwest coordinates if (polyLines.isNotEmpty) { // clearPolyline(); } else { var polyline = Polyline( polylineId: PolylineId(response["routes"][0]["summary"]), points: polylineCoordinatesPointsAll[index], width: 10, color: Colors.blue, ); polyLines.add(polyline); rideConfirm = false; // isMarkersShown = true; update(); } } void updateCameraForDistanceAfterGetMap() { LatLng coord1 = LatLng( double.parse(coordinatesWithoutEmpty.first.split(',')[0]), double.parse(coordinatesWithoutEmpty.first.split(',')[1])); LatLng coord2 = LatLng( double.parse(coordinatesWithoutEmpty.last.split(',')[0]), double.parse(coordinatesWithoutEmpty.last.split(',')[1])); LatLng northeast; LatLng southwest; if (coord1.latitude > coord2.latitude) { northeast = coord1; southwest = coord2; } else { northeast = coord2; southwest = coord1; } // Create the LatLngBounds object LatLngBounds bounds = LatLngBounds(northeast: northeast, southwest: southwest); // Fit the camera to the bounds var cameraUpdate = CameraUpdate.newLatLngBounds(bounds, 180); mapController!.animateCamera(cameraUpdate); update(); } int selectedIndex = -1; // Initialize with no selection void selectCarFromList(int index) { selectedIndex = index; // Update selected index carTypes.forEach( (element) => element.isSelected = false); // Reset selection flags carTypes[index].isSelected = true; update(); } showBottomSheet1() async { await bottomSheet(); isBottomSheetShown = true; heightBottomSheetShown = 250; update(); } final promo = TextEditingController(); bool promoTaken = false; applyPromoCodeToPassenger(BuildContext context) async { if (promoTaken == false) { if (promoFormKey.currentState!.validate()) { CRUD().get(link: AppLink.getPassengersPromo, payload: { 'promo_code': promo.text, }).then((value) { if (value == 'failure') { MyDialog().getDialog( 'Promo Ended'.tr, 'The promotion period has ended.'.tr, () { Get.back(); }, ); } else if (totalPassengerComfort > 30 || totalPassengerLady > 30 || totalPassengerSpeed > 20 || totalPassengerBalash > 20) { var decode = jsonDecode(value); if (decode["status"] == "success") { Get.snackbar('Promo Code Accepted'.tr, '', backgroundColor: AppColor.greenColor); var firstElement = decode["message"][0]; double burc = double.parse(box.read(BoxName.passengerWalletTotal)); if (burc < 0) { int discountPercentage = int.parse(firstElement['amount']); // 1. Calculate and apply discount for totalPassengerComfort totalPassengerComfortDiscount = totalPassengerComfort * discountPercentage / 100; Log.print( 'totalPassengerComfortDiscount: $totalPassengerComfortDiscount'); // Apply the formula: totalPassengerComfort + (-1 * burc) - discount totalPassengerComfort = totalPassengerComfort + (-1 * burc) - totalPassengerComfortDiscount; // 2. Calculate and apply discount for totalPassengerLady totalPassengerLadyDiscount = totalPassengerLady * discountPercentage / 100; // Apply the formula: totalPassengerLady + (-1 * burc) - discount totalPassengerLady = totalPassengerLady + (-1 * burc) - totalPassengerLadyDiscount; // 3. Calculate and apply discount for totalPassengerSpeed totalPassengerSpeedDiscount = totalPassengerSpeed * discountPercentage / 100; // Apply the formula: totalPassengerSpeed + (-1 * burc) - discount totalPassengerSpeed = totalPassengerSpeed + (-1 * burc) - totalPassengerSpeedDiscount; // 4. Calculate and apply discount for totalPassengerBalash totalPassengerBalashDiscount = totalPassengerBalash * discountPercentage / 100; // Apply the formula: totalPassengerBalash + (-1 * burc) - discount totalPassengerBalash = totalPassengerBalash + (-1 * burc) - totalPassengerBalashDiscount; // Mark promo as taken promoTaken = true; // Update UI update(); } else { int discountPercentage = int.parse(firstElement['amount']); // Calculate discounts for each category, ensuring they don't exceed 25 totalPassengerComfortDiscount = totalPassengerComfort * discountPercentage / 100; if (totalPassengerComfortDiscount > 25) { totalPassengerComfortDiscount = 25; // Limit the discount to 25 } Log.print( 'totalPassengerComfortDiscount: $totalPassengerComfortDiscount'); totalPassengerComfort = totalPassengerComfort - totalPassengerComfortDiscount; totalPassengerLadyDiscount = totalPassengerLady * discountPercentage / 100; if (totalPassengerLadyDiscount > 25) { totalPassengerLadyDiscount = 25; // Limit the discount to 25 } totalPassengerLady = totalPassengerLady - totalPassengerLadyDiscount; totalPassengerSpeedDiscount = totalPassengerSpeed * discountPercentage / 100; if (totalPassengerSpeedDiscount > 25) { totalPassengerSpeedDiscount = 25; // Limit the discount to 25 } totalPassengerSpeed = totalPassengerSpeed - totalPassengerSpeedDiscount; totalPassengerBalashDiscount = totalPassengerBalash * discountPercentage / 100; if (totalPassengerBalashDiscount > 25) { totalPassengerBalashDiscount = 25; // Limit the discount to 25 } totalPassengerBalash = totalPassengerBalash - totalPassengerBalashDiscount; // Trigger UI update update(); } totalDriver = totalDriver - (totalDriver * int.parse(firstElement['amount']) / 100); promoTaken = true; // Launch confetti for success feedback Confetti.launch( context, options: const ConfettiOptions( particleCount: 100, spread: 70, y: 0.6), ); update(); Get.back(); Future.delayed(const Duration(microseconds: 111)); } } else { Get.snackbar('Lowest Price Achieved'.tr, 'Cannot apply further discounts.'.tr, backgroundColor: AppColor.yellowColor); } }); } } else { MyDialog().getDialog( 'Promo Already Used'.tr, 'You have already used this promo code.'.tr, () { Get.back(); }); } } double getDistanceFromText(String distanceText) { // Remove any non-digit characters from the distance text String distanceValue = distanceText.replaceAll(RegExp(r'[^0-9.]+'), ''); // Parse the extracted numerical value as a double double distance = double.parse(distanceValue); return distance; } double costForDriver = 0; double totalPassengerSpeed = 0; double totalPassengerBalash = 0; double totalPassengerLady = 0; double totalPassengerRayehGai = 0; double totalPassengerRayehGaiComfort = 0; double totalPassengerRayehGaiBalash = 0; Future bottomSheet() async { if (data.isNotEmpty) { durationToAdd = Duration(seconds: durationToRide); hours = durationToAdd.inHours; minutes = (durationToAdd.inMinutes % 60).round(); DateTime currentTime = DateTime.now(); newTime = currentTime.add(durationToAdd); averageDuration = (durationToRide / 60) / distance; // costDuration = (durationToRide / 60) * averageDuration * 0.016; costDuration = (durationToRide / 60).floorToDouble(); 'passengerWalletTotal----- ${box.read(BoxName.passengerWalletTotal)}'; double costComfort, costSpeed, costDelivery, costBalash, costLady, costRayehGai, costRayehGaiBalash, costRayehGaiComfort = 0; update(); if (startNameAddress.toLowerCase().contains('airport') || endNameAddress.toLowerCase().contains('airport') || startNameAddress.contains('مطار') || startNameAddress.contains('المطار') || endNameAddress.contains('مطار') || endNameAddress.contains('المطار')) { costComfort = (distance * comfortPrice) + (costDuration * latePrice) + 20; costSpeed = (distance * speedPrice) + (costDuration * latePrice) + 20; costBalash = (distance * (speedPrice - 1)) + (costDuration * latePrice) + 20; costDelivery = (distance * deliveryPrice) + (costDuration * latePrice) + 20; costLady = (distance * comfortPrice + 2) + (costDuration * latePrice) + 20; costRayehGai = (distance * 2 * speedPrice) - ((distance * 1 * speedPrice) * .4) + costDuration * 2 * latePrice + 20; costRayehGaiComfort = (distance * 2 * comfortPrice) - ((distance * 1 * comfortPrice) * .4) + costDuration * 2 * latePrice + 20; costRayehGaiBalash = (distance * 2 * (speedPrice - 1)) - ((distance * 1 * (speedPrice - 1)) * .4) + costDuration * 2 * latePrice + 20; update(); } else if (currentTime.hour >= 21 && currentTime.hour < 0) { // costDistance = distance * latePrice; costComfort = (distance * comfortPrice) + costDuration * latePrice; costSpeed = (distance * speedPrice) + costDuration * latePrice; costBalash = (distance * (speedPrice - 1)) + costDuration * latePrice; costDelivery = (distance * deliveryPrice) + costDuration * latePrice; costLady = (distance * comfortPrice + 2) + costDuration * latePrice; costRayehGai = (distance * 2 * speedPrice) - ((distance * 1 * speedPrice) * .4) + costDuration * 2 * latePrice; costRayehGaiComfort = (distance * 2 * comfortPrice) - ((distance * 1 * comfortPrice) * .4) + costDuration * 2 * latePrice; costRayehGaiBalash = (distance * 2 * (speedPrice - 1)) - ((distance * 1 * (speedPrice - 1)) * .4) + costDuration * 2 * latePrice; update(); } else if (currentTime.hour >= 1 && currentTime.hour < 5) { // costDistance = distance * latePrice; if (startNameAddress.contains('club') || startNameAddress.contains('nightclub') || startNameAddress.contains('ديسكو') || startNameAddress.contains('ملهى ليلي') || startNameAddress.contains('Night club')) { // Your code here costComfort = (distance * comfortPrice) + costDuration * (latePrice + .5) * 2; costSpeed = (distance * speedPrice) + costDuration * (latePrice + .5) * 2; costBalash = (distance * (speedPrice - 1)) + costDuration * (latePrice + .5) * 2; costDelivery = (distance * deliveryPrice) + costDuration * (latePrice + .5) * 2; costLady = (distance * comfortPrice + 2) + costDuration * (latePrice + .5) * 2; costRayehGai = (distance * 2 * speedPrice) - ((distance * 1 * speedPrice) * .4) + costDuration * 2 * (latePrice + .5) * 2; costRayehGaiComfort = (distance * 2 * comfortPrice) - ((distance * 1 * comfortPrice) * .4) + costDuration * 2 * (latePrice + .5) * 2; costRayehGaiBalash = (distance * 2 * (speedPrice - 1)) - ((distance * 1 * (speedPrice - 1)) * .4) + costDuration * 2 * (latePrice + .5) * 2; update(); } costComfort = (distance * comfortPrice) + costDuration * (latePrice + .5); costSpeed = (distance * speedPrice) + costDuration * (latePrice + .5); costBalash = (distance * (speedPrice - 1)) + costDuration * (latePrice + .5); costDelivery = (distance * deliveryPrice) + costDuration * (latePrice + .5); costLady = (distance * comfortPrice + 2) + costDuration * (latePrice + .5); costRayehGai = (distance * 2 * speedPrice) - ((distance * 1 * speedPrice) * .4) + costDuration * 2 * latePrice; costRayehGaiComfort = (distance * 2 * comfortPrice) - ((distance * 1 * comfortPrice) * .4) + costDuration * 2 * latePrice; costRayehGaiBalash = (distance * 2 * (speedPrice - 1)) - ((distance * 1 * (speedPrice - 1)) * .4) + costDuration * 2 * latePrice; update(); } else if (currentTime.hour >= 14 && currentTime.hour <= 17) { // if (averageDuration > 2.5) { // costDistance = distance * heavyPrice; costComfort = (distance * comfortPrice) + costDuration * heavyPrice; costSpeed = (distance * speedPrice) + costDuration * heavyPrice; costBalash = (distance * (speedPrice - 1)) + costDuration * heavyPrice; costDelivery = (distance * deliveryPrice) + costDuration * heavyPrice; costLady = (distance * comfortPrice + 2) + costDuration * heavyPrice; costRayehGai = (distance * 2 * speedPrice) - ((distance * 1 * speedPrice) * .4) + costDuration * 2 * heavyPrice; costRayehGaiComfort = (distance * 2 * comfortPrice) - ((distance * 1 * comfortPrice) * .4) + costDuration * 2 * heavyPrice; costRayehGaiBalash = (distance * 2 * (speedPrice - 1)) - ((distance * 1 * (speedPrice - 1)) * .4) + costDuration * 2 * heavyPrice; update(); // } / } else { // costDistance = distance * (naturePrice - .1); costComfort = (distance * comfortPrice) + costDuration; costSpeed = (distance * speedPrice) + costDuration; costBalash = (distance * (speedPrice - 1)) + costDuration; costDelivery = (distance * deliveryPrice) + costDuration; costLady = (distance * comfortPrice + 2) + costDuration; costRayehGai = (distance * 2 * speedPrice) - ((distance * 1 * speedPrice) * .4) + costDuration * 2; costRayehGaiComfort = (distance * 2 * comfortPrice) - ((distance * 1 * comfortPrice) * .4) + costDuration * 2; costRayehGaiBalash = (distance * 2 * (speedPrice - 1)) - ((distance * 1 * (speedPrice - 1)) * .4) + costDuration * 2; update(); } var totalDriver1 = costDistance + costDuration; totalCostPassenger = totalDriver1 + (totalDriver1 * kazan / 100); totalPassenger = costSpeed + (costSpeed * kazan / 100); if (isInUniversity) { Log.print('isInUniversity: $isInUniversity'); totalPassengerComfort = 20 + (costComfort + (costComfort * kazan / 100)).ceilToDouble(); totalPassengerLady = 20 + (costLady + (costLady * kazan / 100)).ceilToDouble(); totalPassengerSpeed = 20 + (costSpeed + (costSpeed * kazan / 100)).ceilToDouble(); totalPassengerBalash = 20 + (costBalash + (costBalash * kazan / 100)).ceilToDouble(); totalPassengerRayehGai = (costRayehGai + (costRayehGai * kazan / 100)).ceilToDouble(); totalPassengerRayehGaiComfort = (costRayehGaiComfort + (costRayehGaiComfort * kazan / 100)) .ceilToDouble(); totalPassengerRayehGaiBalash = (costRayehGaiBalash + (costRayehGaiBalash * kazan / 100)) .ceilToDouble(); totalPassengerComfortDiscount = totalPassengerComfort + totalPassengerComfort * (kazan - 0) / 100; totalPassengerLadyDiscount = totalPassengerLady + totalPassengerLady * (kazan - 0) / 100; totalPassengerSpeedDiscount = totalPassengerSpeed + totalPassengerSpeed * (kazan) / 100; totalPassengerBalashDiscount = totalPassengerBalash + totalPassengerBalash * (kazan) / 100; totalPassengerRaihGaiDiscount = totalPassengerRayehGai + totalPassengerRayehGai * (kazan) / 100; totalPassengerScooter = (costDelivery + (costDelivery * kazan / 100)).ceilToDouble(); totalPassengerComfort = totalPassengerComfortDiscount - (totalPassengerComfortDiscount * kazan / 100); totalPassengerSpeed = totalPassengerSpeedDiscount - (totalPassengerSpeedDiscount * kazan / 100); totalPassengerBalash = totalPassengerBalashDiscount - (totalPassengerBalashDiscount * kazan / 100); totalPassengerLady = totalPassengerLadyDiscount - (totalPassengerLadyDiscount * kazan / 100); totalDriver = totalDriver1 + (totalDriver1 * kazan / 100); tax = totalCostPassenger * kazan / 100; totalME = totalCostPassenger - tax; costForDriver = fuelPrice * (20 / 210) * distance; } else { Log.print('isInUniversity: $isInUniversity'); totalPassengerComfort = (costComfort + (costComfort * kazan / 100)).ceilToDouble(); totalPassengerLady = (costLady + (costLady * kazan / 100)).ceilToDouble(); totalPassengerSpeed = (costSpeed + (costSpeed * kazan / 100)).ceilToDouble(); totalPassengerBalash = (costBalash + (costBalash * kazan / 100)).ceilToDouble(); totalPassengerRayehGai = (costRayehGai + (costRayehGai * kazan / 100)).ceilToDouble(); totalPassengerRayehGaiComfort = (costRayehGaiComfort + (costRayehGaiComfort * kazan / 100)) .ceilToDouble(); totalPassengerRayehGaiBalash = (costRayehGaiBalash + (costRayehGaiBalash * kazan / 100)) .ceilToDouble(); totalPassengerComfortDiscount = totalPassengerComfort + totalPassengerComfort * (kazan - 0) / 100; totalPassengerLadyDiscount = totalPassengerLady + totalPassengerLady * (kazan - 0) / 100; totalPassengerSpeedDiscount = totalPassengerSpeed + totalPassengerSpeed * (kazan) / 100; totalPassengerBalashDiscount = totalPassengerBalash + totalPassengerBalash * (kazan) / 100; totalPassengerRaihGaiDiscount = totalPassengerRayehGai + totalPassengerRayehGai * (kazan) / 100; totalPassengerScooter = (costDelivery + (costDelivery * kazan / 100)).ceilToDouble(); totalPassengerComfort = totalPassengerComfortDiscount - (totalPassengerComfortDiscount * kazan / 100); totalPassengerSpeed = totalPassengerSpeedDiscount - (totalPassengerSpeedDiscount * kazan / 100); totalPassengerBalash = totalPassengerBalashDiscount - (totalPassengerBalashDiscount * kazan / 100); totalPassengerLady = totalPassengerLadyDiscount - (totalPassengerLadyDiscount * kazan / 100); totalDriver = totalDriver1 + (totalDriver1 * kazan / 100); tax = totalCostPassenger * kazan / 100; totalME = totalCostPassenger - tax; costForDriver = fuelPrice * (20 / 210) * distance; } if (totalPassengerSpeed < 20) { // for eygpt 20 le open ride totalCostPassenger = 20; totalPassengerSpeed = 20; totalPassengerBalash = 20; totalPassengerComfort = 30; totalPassengerLady = 30; totalPassengerScooter = 18; } else { totalPassenger = totalCostPassenger; update(); } if (double.parse(box.read(BoxName.passengerWalletTotal)) < 0) { totalPassenger = totalPassenger + (-1) * (double.parse(box.read(BoxName.passengerWalletTotal))); totalPassengerComfort = totalPassengerComfort + (-1) * (double.parse(box.read(BoxName.passengerWalletTotal))); totalPassengerLady = totalPassengerLady + (-1) * (double.parse(box.read(BoxName.passengerWalletTotal))); totalPassengerBalash = totalPassengerBalash + (-1) * (double.parse(box.read(BoxName.passengerWalletTotal))); totalPassengerScooter = totalPassengerScooter + (-1) * (double.parse(box.read(BoxName.passengerWalletTotal))); totalPassengerRayehGai = totalPassengerScooter + (-1) * (double.parse(box.read(BoxName.passengerWalletTotal))); update(); } // } // buttomSheetMapPage(); changeBottomSheetShown(); } else {} } addToken() async { await CRUD() .post(link: "${AppLink.server}/ride/firebase/add.php", payload: { 'token': box.read(BoxName.tokenFCM), 'passengerID': box.read(BoxName.passengerID).toString() }); CRUD().post( link: "${AppLink.seferAlexandriaServer}/ride/firebase/add.php", payload: { 'token': box.read(BoxName.tokenFCM), 'passengerID': box.read(BoxName.passengerID).toString() }); CRUD().post( link: "${AppLink.seferGizaServer}/ride/firebase/add.php", payload: { 'token': box.read(BoxName.tokenFCM), 'passengerID': box.read(BoxName.passengerID).toString() }); } List polylineCoordinate = []; String? cardNumber; void readyWayPoints() { hintTextwayPointStringAll = [ hintTextwayPoint0, hintTextwayPoint1, hintTextwayPoint2, hintTextwayPoint3, hintTextwayPoint4, ]; polylineCoordinatesPointsAll = [ polylineCoordinates0, polylineCoordinates1, polylineCoordinates2, polylineCoordinates3, polylineCoordinates4, ]; allTextEditingPlaces = [ wayPoint0Controller, wayPoint1Controller, wayPoint2Controller, wayPoint3Controller, wayPoint4Controller, ]; currentLocationToFormPlacesAll = [ currentLocationToFormPlaces0, currentLocationToFormPlaces1, currentLocationToFormPlaces2, currentLocationToFormPlaces3, currentLocationToFormPlaces4, ]; placeListResponseAll = [ wayPoint0, wayPoint1, wayPoint2, wayPoint3, wayPoint4 ]; startLocationFromMapAll = [ startLocationFromMap0, startLocationFromMap1, startLocationFromMap2, startLocationFromMap3, startLocationFromMap4, ]; currentLocationStringAll = [ currentLocationString0, currentLocationString1, currentLocationString2, currentLocationString3, currentLocationString4, ]; placesCoordinate = [ placesCoordinate0, placesCoordinate1, placesCoordinate2, placesCoordinate3, placesCoordinate4, ]; update(); } List driversForMishwari = []; Future selectDriverAndCarForMishwariTrip() async { // Calculate the bounds for 20km double latitudeOffset = 0.1795; // 20km range in latitude double longitudeOffset = 0.2074; // 20km range in longitude // Calculate bounding box based on passenger's location double southwestLat = passengerLocation.latitude - latitudeOffset; double northeastLat = passengerLocation.latitude + latitudeOffset; double southwestLon = passengerLocation.longitude - longitudeOffset; double northeastLon = passengerLocation.longitude + longitudeOffset; // Create the payload with calculated bounds var payload = { 'southwestLat': southwestLat.toString(), 'northeastLat': northeastLat.toString(), 'southwestLon': southwestLon.toString(), 'northeastLon': northeastLon.toString(), }; try { // Fetch data from the API var res = await CRUD().get( link: AppLink.selectDriverAndCarForMishwariTrip, payload: payload); if (res != 'failure') { // Check if response is valid JSON try { var d = jsonDecode(res); driversForMishwari = d['message']; Log.print('driversForMishwari: ${driversForMishwari}'); update(); } catch (e) { // Handle invalid JSON format print("Error decoding JSON: $e"); return 'Server returned invalid data. Please try again later.'; } } else { return 'No driver available now, try again later. Thanks for using our app.' .tr; } } catch (e) { // Handle network or other exceptions print("Error fetching data: $e"); return 'There was an issue connecting to the server. Please try again later.' .tr; } } final Rx selectedDateTime = DateTime.now().obs; void updateDateTime(DateTime newDateTime) { selectedDateTime.value = newDateTime; } Future mishwariOption() async { isLoading = true; update(); // add dialoug for select driver and car await selectDriverAndCarForMishwariTrip(); Future.delayed(Duration.zero); isLoading = false; update(); Get.to(() => CupertinoDriverListWidget()); // changeCashConfirmPageShown(); } var driverIdVip = ''; Future saveTripData( Map driver, DateTime tripDateTime) async { try { // Prepare trip data Map tripData = { 'id': driver['driver_id'].toString(), // Ensure the id is a string 'phone': driver['phone'], 'gender': driver['gender'], 'name': driver['NAME'], 'name_english': driver['name_english'], 'address': driver['address'], 'religion': driver['religion'] ?? 'UnKnown', 'age': driver['age'].toString(), // Convert age to String 'education': driver['education'] ?? 'UnKnown', //startlocationname 'license_type': driver['license_type'] ?? 'UnKnown', 'national_number': driver['national_number'] ?? 'UnKnown', 'car_plate': driver['car_plate'], 'make': driver['make'], 'model': driver['model'], 'year': driver['year'].toString(), // Convert year to String 'color': driver['color'], 'color_hex': driver['color_hex'], 'displacement': driver['displacement'], 'fuel': driver['fuel'], 'token': driver['token'], 'rating': driver['rating'].toString(), // Convert rating to String 'countRide': driver['ride_count'].toString(), // Convert countRide to String 'passengerId': box.read(BoxName.passengerID), 'timeSelected': tripDateTime.toIso8601String(), 'status': 'pending', 'startNameAddress': startNameAddress.toString(), 'locationCoordinate': '${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}', }; Log.print('tripData: $tripData'); // Send data to server var response = await CRUD().post(link: AppLink.addMishwari, payload: tripData); // Log.print('response: $response'); if (response != 'failure') { // Trip saved successfully // Get.snackbar('Success'.tr, 'Trip booked successfully'.tr); var id = response['message']['id'].toString(); 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]["start_location"]['lat']},${data[0]["start_location"]['lng']}', "date": DateTime.now().toString(), "time": DateTime.now().toString(), "endtime": DateTime.now().add(const Duration(hours: 2)).toString(), "price": '50', "passenger_id": box.read(BoxName.passengerID).toString(), "driver_id": driver['driver_id'].toString(), "status": "waiting", 'carType': 'vip', "price_for_driver": '50', "price_for_passenger": '50', "distance": '20', "paymentMethod": 'cash', }).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}'); } }); if (AppLink.endPoint != AppLink.seferCairoServer) { await CRUD().post( link: "${AppLink.endPoint}/ride/mishwari/add.php", payload: tripData); 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]["start_location"]['lat']},${data[0]["start_location"]['lng']}', "date": DateTime.now().toString(), "time": DateTime.now().toString(), "endtime": DateTime.now().add(const Duration(hours: 2)).toString(), "price": '50', "passenger_id": box.read(BoxName.passengerID).toString(), "driver_id": driver['driver_id'].toString(), "status": "waiting", 'carType': 'vip', "price_for_driver": '50', "price_for_passenger": '50', "distance": '20', "paymentMethod": 'cash', }); } driverIdVip = driver['driver_id'].toString(); driverId = driver['driver_id'].toString(); DateTime timeSelected = DateTime.parse(tripDateTime.toIso8601String()); Get.find().scheduleNotificationsForTimeSelected( "Your trip is scheduled".tr, "Don't forget your ride!".tr, "tone1", timeSelected); // Optionally, set up local notification or send a push notification await FirebaseMessagesController().sendNotificationToDriverMAP( 'OrderVIP', rideId.toString(), driver['token'].toString(), [ id, rideId, driver['id'], passengerLocation.latitude.toString(), startNameAddress.toString(), passengerLocation.longitude.toString(), box.read(BoxName.name).toString(), box.read(BoxName.passengerID).toString(), box.read(BoxName.phone).toString(), box.read(BoxName.email).toString(), box.read(BoxName.passengerPhotoUrl).toString(), box.read(BoxName.tokenFCM).toString(), driver['token'].toString(), ], 'order.wav'); if (response['message'] == "Trip updated successfully") { mySnackbarSuccess("Trip updated successfully".tr); Log.print( 'previous_driver_token: ${response['previous_driver_token']}'); FirebaseMessagesController().sendNotificationToDriverMAP( 'Order VIP Canceld'.tr, 'Passenger cancel order'.tr, response['previous_driver_token'].toString(), [], 'cancel.wav', ); } // data = []; isBottomSheetShown = false; update(); Get.to(() => VipWaittingPage()); } else { throw Exception('Failed to save trip'); } } catch (e) { // Show error message with more details for debugging Get.snackbar('Error'.tr, 'Failed to book trip: $e'.tr, backgroundColor: AppColor.redColor); Log.print('Error: $e'); } } cancelVip(String token, tripId) async { // FirebaseMessagesController().sendNotificationToDriverMAP( // 'Order VIP Canceld'.tr, // 'Passenger cancel order'.tr, // token, // [], // 'cancel.wav', // ); var res = await CRUD() .post(link: AppLink.cancelMishwari, payload: {'id': tripId}); if (res != 'failur') { Get.back(); mySnackbarSuccess('You canceled VIP trip'.tr); } } sendToDriverAgain(String token) { FirebaseMessagesController().sendNotificationToDriverMAP( 'Order VIP Canceld'.tr, 'Passenger cancel order'.tr, token, [], 'cancel.wav', ); } initilizeGetStorage() async { if (box.read(BoxName.addWork) == null) { box.write(BoxName.addWork, 'addWork'); } if (box.read(BoxName.addHome) == null) { box.write(BoxName.addHome, 'addHome'); } } late List recentPlaces = []; getFavioratePlaces0() async { recentPlaces = await sql.getCustomQuery( 'SELECT DISTINCT latitude, longitude, name, rate FROM ${TableName.recentLocations}'); } getFavioratePlaces() async { recentPlaces = await sql.getCustomQuery( 'SELECT * FROM ${TableName.recentLocations} ORDER BY createdAt DESC'); // Log.print('recentPlaces: ${recentPlaces}'); } double passengerRate = 5; double comfortPrice = 8; double speedPrice = 4; double mashwariPrice = 4; double deliveryPrice = 1.2; getKazanPercent() async { var res = await CRUD().get( link: AppLink.getKazanPercent, payload: {'country': box.read(BoxName.countryCode).toString()}, ); if (res != 'failure') { var json = jsonDecode(res); kazan = double.parse(json['message'][0]['kazan']); naturePrice = double.parse(json['message'][0]['naturePrice']); heavyPrice = double.parse(json['message'][0]['heavyPrice']); latePrice = double.parse(json['message'][0]['latePrice']); comfortPrice = double.parse(json['message'][0]['comfortPrice']); speedPrice = double.parse(json['message'][0]['speedPrice']); deliveryPrice = double.parse(json['message'][0]['deliveryPrice']); mashwariPrice = double.parse(json['message'][0]['freePrice']); fuelPrice = double.parse(json['message'][0]['fuelPrice']); } } void startFetchingData() { Timer.periodic(const Duration(milliseconds: 50), (Timer timer) async { await getKazanPercent(); }); } getPassengerRate() async { var res = await CRUD().get( link: AppLink.getPassengerRate, payload: {'passenger_id': box.read(BoxName.passengerID)}); if (res != 'failure') { if (jsonDecode(res)['message']['rating'] == null) { passengerRate = 5; } else { passengerRate = jsonDecode(res)['message']['rating'].toDouble(); } } else { passengerRate = 5; } } firstTimeRunToGetCoupon() async { // Check if it's the first time and the app is installed and gift token is available if (box.read(BoxName.isFirstTime).toString() == '0' && box.read(BoxName.isInstall).toString() == '1' && box.read(BoxName.isGiftToken).toString() == '0') { var promo, discount, validity; var resPromo = await CRUD().get(link: AppLink.getPromoFirst, payload: { "passengerID": box.read(BoxName.passengerID).toString(), }); if (resPromo != 'failure') { var d1 = jsonDecode(resPromo); promo = d1['message']['promo_code']; discount = d1['message']['amount']; validity = d1['message']['validity_end_date']; } box.write(BoxName.isFirstTime, '1'); // Show a full-screen modal styled as an ad Get.dialog( AlertDialog( contentPadding: EdgeInsets.zero, // Removes the padding around the content content: SizedBox( width: 300, // Match the width of PromoBanner // height: 250, // Match the height of PromoBanner child: PromoBanner( promoCode: promo, discountPercentage: discount, validity: validity, ), ), ), ); } } var k; @override void onInit() async { mapAPIKEY = await storage.read(key: BoxName.mapAPIKEY); k = await getAIKey('HERE_API'); getFavioratePlaces(); readyWayPoints(); addCustomPicker(); addCustomCarIcon(); addCustomLadyIcon(); addCustomMotoIcon(); addCustomStepIcon(); addCustomStartIcon(); addCustomEndIcon(); // addToken(); await getLocation(); getPassengerLocationUniversity(); _initializePolygons(); // await addToken(); getKazanPercent(); getPassengerRate(); getRideStatusFromStartApp(); reloadStartApp = false; startMarkerReloading(); Get.put(TextToSpeechController()); box.write(BoxName.carType, 'yet'); box.write(BoxName.tipPercentage, '0'); Get.put(AudioRecorderController()); // await getNearestDriverByPassengerLocation(); firstTimeRunToGetCoupon(); initilizeGetStorage(); cardNumber = await SecureStorage().readData(BoxName.cardNumber); super.onInit(); } uploadPassengerLocation() async { await CRUD().post(link: AppLink.addpassengerLocation, payload: { "passengerId": box.read(BoxName.passengerID), "lat": passengerLocation.latitude.toString(), "lng": passengerLocation.longitude.toString(), "rideId": rideId.toString() }); } } class CarLocation { final String id; final double latitude; final double longitude; final double distance; final double duration; CarLocation({ required this.id, required this.latitude, required this.longitude, this.distance = 10000, this.duration = 10000, }); }