Files
tripz/lib/controller/home/map_passenger_controller.dart
Hamza-Ayed 8813b4dccd 12/17/1
2024-12-17 00:41:00 +03:00

5260 lines
187 KiB
Dart

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<FormState>();
final promoFormKey = GlobalKey<FormState>();
final messagesFormKey = GlobalKey<FormState>();
final increaseFeeFormKey = GlobalKey<FormState>();
List data = [];
List<LatLng> bounds = [];
List placesStart = [];
List<String> driversToken = [];
LatLng previousLocationOfDrivers = const LatLng(0, 0);
double angleDegrees = 0;
LatLng currentLocationOfDrivers = const LatLng(0, 0);
List<TextEditingController> allTextEditingPlaces = [];
List placesDestination = [];
List wayPoint0 = [];
List wayPoint1 = [];
List wayPoint2 = [];
List wayPoint3 = [];
List wayPoint4 = [];
List<List<dynamic>> placeListResponseAll = [];
List<Widget> placeListResponse = [
formSearchPlaces(0),
formSearchPlaces(1),
formSearchPlaces(2),
formSearchPlaces(3),
];
LatLngBounds? boundsdata;
List<Marker> markers = [];
List<Polyline> 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<LatLng> polylineCoordinates = [];
List<LatLng> polylineCoordinates0 = [];
List<LatLng> polylineCoordinates1 = [];
List<LatLng> polylineCoordinates2 = [];
List<LatLng> polylineCoordinates3 = [];
List<LatLng> polylineCoordinates4 = [];
List<List<LatLng>> polylineCoordinatesPointsAll = [];
List carsLocationByPassenger = [];
List<LatLng> 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<CarLocationModel> carLocationsModels = <CarLocationModel>[];
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<String> currentLocationStringAll = [];
List<String> hintTextwayPointStringAll = [];
var placesCoordinate = <String>[];
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<String> 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<AnimatedContainer>();
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<int> _timerStreamController = StreamController<int>();
Stream<int> 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<int>();
// 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<String> _beginRideStreamController =
StreamController<String>.broadcast();
Stream<String> 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<String, dynamic> tripData =
box.read(BoxName.tripData) as Map<String, dynamic>;
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<TextToSpeechController>();
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<String, double>? 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<String> 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<String> 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<String> pathSegments = uri.pathSegments;
for (var segment in pathSegments) {
if (segment.contains(',')) {
List<String> 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<String, double>? 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<String> 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<void> 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<PaymentController>();
// rideConfirm = true;
// shouldFetch = true;
// isBottomSheetShown = false;
// timeToPassengerFromDriverAfterApplied = 60;
// // Add ride to database
// await CRUD()
// .post(link: "${AppLink.seferCairoServer}/ride/rides/add.php", payload: {
// "start_location":
// '${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
// "end_location":
// '${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
// "date": DateTime.now().toString(),
// "time": DateTime.now().toString(),
// "endtime": durationToAdd.toString(),
// "price": totalPassenger.toStringAsFixed(2),
// "passenger_id": box.read(BoxName.passengerID).toString(),
// "driver_id": dataCarsLocationByPassenger['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<String> body = [
// '${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
// '${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
// totalPassenger.toStringAsFixed(2),
// totalDriver.toStringAsFixed(2),
// durationToRide.toString(),
// distance.toStringAsFixed(2),
// driverId.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<WayPointController>().wayPoints.length > 1
// ? 'haveSteps'
// : 'startEnd',
// placesCoordinate[0],
// placesCoordinate[1],
// placesCoordinate[2],
// placesCoordinate[3],
// placesCoordinate[4],
// costForDriver.toStringAsFixed(2),
// (double.parse(box.read(BoxName.passengerWalletTotal)) < 0
// ? double.parse(box.read(BoxName.passengerWalletTotal))
// .toStringAsFixed(2)
// : '0'),
// box.read(BoxName.email).toString(),
// data[0]['start_address'],
// data[0]['end_address'],
// box.read(BoxName.carType),
// kazan.toStringAsFixed(0),
// passengerRate.toStringAsFixed(2),
// ];
// 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<PaymentController>();
// rideConfirm = true;
// shouldFetch = true;
// isBottomSheetShown = false;
// timeToPassengerFromDriverAfterApplied = 60;
// // confirmRideForAllDriverAvailable();
// for (var i = 0; i < dataCarsLocationByPassenger['message'].length; i++) {
// List<String> body = [
// '${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
// '${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
// totalPassenger.toStringAsFixed(2),
// totalDriver.toStringAsFixed(2),
// durationToRide.toString(),
// distance.toStringAsFixed(2),
// 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<WayPointController>().wayPoints.length > 1
// ? 'haveSteps'
// : 'startEnd',
// placesCoordinate[0],
// placesCoordinate[1],
// placesCoordinate[2],
// placesCoordinate[3],
// placesCoordinate[4],
// costForDriver.toStringAsFixed(2),
// double.parse(box.read(BoxName.passengerWalletTotal)) < 0
// ? double.parse(box.read(BoxName.passengerWalletTotal))
// .toStringAsFixed(2)
// : '0',
// box.read(BoxName.email).toString(),
// data[0]['start_address'],
// data[0]['end_address'],
// box.read(BoxName.carType),
// kazan.toStringAsFixed(0),
// passengerRate.toStringAsFixed(2),
// ];
// // 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<AudioRecorderController>()
// .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<void> 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<void> 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<void> postRideDetailsToServer() async {
final paymentController = Get.find<PaymentController>();
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<String, dynamic> 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<void> 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<String> constructNotificationBody(var driverData) {
final paymentController = Get.find<PaymentController>();
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<WayPointController>().wayPoints.length > 1
? 'haveSteps'
: 'startEnd',
placesCoordinate[0],
placesCoordinate[1],
placesCoordinate[2],
placesCoordinate[3],
placesCoordinate[4],
costForDriver.toStringAsFixed(2),
(double.parse(box.read(BoxName.passengerWalletTotal)) < 0
? double.parse(box.read(BoxName.passengerWalletTotal))
.toStringAsFixed(2)
: '0'),
box.read(BoxName.email).toString(),
data[0]['start_address'],
data[0]['end_address'],
box.read(BoxName.carType),
kazan.toStringAsFixed(0),
passengerRate.toStringAsFixed(2),
];
}
StreamController<String> _rideStatusStreamController =
StreamController<String>.broadcast();
Stream<String> get rideStatusStream => _rideStatusStreamController.stream;
Future<void> 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<String> 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<String, Timer> _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<bool> 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<Map<String, dynamic>> 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<String, dynamic> 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<Marker?>().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<String, dynamic>) {
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<LatLng> 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<List<LatLng>> universityPolygons, List<String> 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 = <Polygon>{}.obs;
// Initialize polygons from UniversitiesPolygons
void _initializePolygons() {
List<List<LatLng>> universityPolygons =
UniversitiesPolygons.universityPolygons;
List<String> 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<String, dynamic> 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<Marker> 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<Marker?>().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<void> 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<WayPointController>().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<WayPointController>().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<void> 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<void> 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<String> 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<void> 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<LocationController>().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<CarLocation?> 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<CarLocation?> 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<PaymentController>()
.payToDriverForCancelAfterAppliedAndHeNearYou(rideId);
// isCancelRidePageShown = true;
// update();
},
);
},
),
],
),
);
// cancel: MyElevatedButton(
// title: 'No.Iwant Cancel Trip.'.tr, onPressed: () {}));
}
}
List<double> 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<String> 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<String> 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<LatLng> 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<DateTime> 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<void> saveTripData(
Map<String, dynamic> driver, DateTime tripDateTime) async {
try {
// Prepare trip data
Map<String, dynamic> 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<NotificationController>().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,
});
}