This commit is contained in:
Hamza-Ayed
2024-08-03 00:50:14 +03:00
parent 74abae1b38
commit 871b9a4d09
24 changed files with 689 additions and 211 deletions

View File

@@ -81,6 +81,21 @@ class RegisterController extends GetxController {
update();
}
bool isValidEgyptianPhoneNumber(String phoneNumber) {
// Remove any whitespace from the phone number
phoneNumber = phoneNumber.replaceAll(RegExp(r'\s+'), '');
// Check if the phone number has exactly 11 digits
if (phoneNumber.length != 11) {
return false;
}
// Check if the phone number starts with 010, 011, 012, or 015
RegExp validPrefixes = RegExp(r'^01[0125]\d{8}$');
return validPrefixes.hasMatch(phoneNumber);
}
sendOtpMessage() async {
SmsEgyptController smsEgyptController = Get.put(SmsEgyptController());
@@ -89,18 +104,33 @@ class RegisterController extends GetxController {
update();
if (formKey3.currentState!.validate()) {
if (box.read(BoxName.countryCode) == 'Egypt') {
var responseCheker = await CRUD()
.post(link: AppLink.checkPhoneNumberISVerfiedPassenger, payload: {
'phone_number': '+2${phoneController.text}',
});
if (responseCheker != 'failure') {
var d = jsonDecode(responseCheker);
if (d['message'][0]['verified'].toString() == '1') {
Get.snackbar('Phone number is verified before'.tr, '',
backgroundColor: AppColor.greenColor);
box.write(BoxName.isVerified, '1');
box.write(BoxName.phone, '+2${phoneController.text}');
Get.offAll(const MapPagePassenger());
if (isValidEgyptianPhoneNumber(phoneController.text)) {
var responseCheker = await CRUD()
.post(link: AppLink.checkPhoneNumberISVerfiedPassenger, payload: {
'phone_number': '+2${phoneController.text}',
});
if (responseCheker != 'failure') {
var d = jsonDecode(responseCheker);
if (d['message'][0]['verified'].toString() == '1') {
Get.snackbar('Phone number is verified before'.tr, '',
backgroundColor: AppColor.greenColor);
box.write(BoxName.isVerified, '1');
box.write(BoxName.phone, '+2${phoneController.text}');
Get.offAll(const MapPagePassenger());
} else {
await CRUD().post(link: AppLink.sendVerifyOtpMessage, payload: {
'phone_number': '+2${phoneController.text}',
'token': randomNumber.toString(),
});
await smsEgyptController.sendSmsEgypt(
phoneController.text.toString(), randomNumber.toString());
isSent = true;
remainingTime = 300; // Reset to 5 minutes
startTimer();
isLoading = false;
update();
}
} else {
await CRUD().post(link: AppLink.sendVerifyOtpMessage, payload: {
'phone_number': '+2${phoneController.text}',
@@ -114,22 +144,12 @@ class RegisterController extends GetxController {
startTimer();
isLoading = false;
update();
// Get.snackbar(responseCheker, 'message');
}
} else {
await CRUD().post(link: AppLink.sendVerifyOtpMessage, payload: {
'phone_number': '+2${phoneController.text}',
'token': randomNumber.toString(),
});
await smsEgyptController.sendSmsEgypt(
phoneController.text.toString(), randomNumber.toString());
isSent = true;
remainingTime = 300; // Reset to 5 minutes
startTimer();
isLoading = false;
update();
// Get.snackbar(responseCheker, 'message');
Get.snackbar('Phone Number wrong'.tr, '',
backgroundColor: AppColor.redColor);
}
}
}

View File

@@ -1,5 +1,6 @@
import 'dart:convert';
import 'dart:io';
import 'package:SEFER/views/widgets/my_dialog.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
@@ -13,6 +14,7 @@ import '../../constant/colors.dart';
import '../../constant/links.dart';
import '../../constant/style.dart';
import '../../main.dart';
import '../../print.dart';
import '../../views/Rate/rate_captain.dart';
import '../../views/home/map_page_passenger.dart';
import '../../views/home/profile/promos_passenger_page.dart';
@@ -183,6 +185,29 @@ class FirebaseMessagesController extends GetxController {
driverArrivePassengerDialoge();
update();
} else if (message.notification!.title! == "Cancel Trip from driver".tr) {
Get.back();
Get.defaultDialog(
title: "The driver canceled your ride.".tr,
middleText: "We will look for a new driver.\nPlease wait.".tr,
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () async {
Get.back();
Get.find<MapPassengerController>()
.delayAndFetchRideStatusForAllDriverAvailable(
Get.find<MapPassengerController>().rideId);
},
),
cancel: MyElevatedButton(
title: 'Cancel'.tr,
onPressed: () {
Get.offAll(const MapPagePassenger());
},
)
// Get.find<MapPassengerController>()
// .searchNewDriverAfterRejectingFromDriver();
);
} else if (message.notification!.title! == 'Driver Finish Trip'.tr) {
var myListString = message.data['passengerList'];
var driverList = jsonDecode(myListString) as List<dynamic>;
@@ -547,7 +572,6 @@ class FirebaseMessagesController extends GetxController {
'notification': <String, dynamic>{
'title': title,
'body': body,
// 'sound': 'tone2.wav',
'sound': tone
},
'data': {
@@ -559,13 +583,16 @@ class FirebaseMessagesController extends GetxController {
);
if (response.statusCode == 200) {
// Notification sent successfully
Log.print(
'Notification sent successfully. Status code: ${response.statusCode}');
Log.print('Response body: ${response.body}');
} else {
// Handle error response
'Failed to send notification. Status code: ${response.statusCode}';
Log.print(
'Failed to send notification. Status code: ${response.statusCode}');
Log.print('Response body: ${response.body}');
}
} catch (e) {
// Handle other exceptions
Log.print('Error sending notification: $e');
}
}

View File

@@ -8,6 +8,7 @@ import 'package:SEFER/env/env.dart';
import '../../constant/api_key.dart';
import '../../print.dart';
import 'upload_image.dart';
class CRUD {
@@ -28,6 +29,7 @@ class CRUD {
},
);
print(response.request);
Log.print('payload: ${payload}');
print(response.body);
// print(payload);
// if (response.statusCode == 200) {

View File

@@ -4,21 +4,35 @@ import 'package:SEFER/constant/api_key.dart';
import 'package:SEFER/constant/box_name.dart';
import 'package:SEFER/constant/info.dart';
import 'package:SEFER/constant/links.dart';
import 'package:SEFER/controller/auth/login_controller.dart';
import 'package:SEFER/main.dart';
import 'package:SEFER/views/widgets/elevated_btn.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import '../auth/register_controller.dart';
import 'crud.dart';
class SmsEgyptController extends GetxController {
var headers = {'Content-Type': 'application/json'};
Future<String> getSender() async {
var res = await CRUD().get(link: AppLink.getSender, payload: {});
if (res != 'failure') {
var d = jsonDecode(res)['message'][0]['senderId'].toString();
return d;
} else {
return "Sefer Egy";
}
}
Future<dynamic> sendSmsEgypt(String phone, otp) async {
String sender = await getSender();
var body = jsonEncode({
"username": AppInformation.appName,
"password": AK.smsPasswordEgypt,
"message": "${AppInformation.appName} app code is $otp\ncopy it to app",
"language": box.read(BoxName.lang) == 'en' ? "e" : 'r',
"sender": "Sefer Egy",
"sender": sender, //"Sefer Egy",
"receiver": "2$phone"
});
@@ -28,9 +42,23 @@ class SmsEgyptController extends GetxController {
headers: headers,
);
if (res.statusCode == 200) {
if (jsonDecode(res.body)['message'].toString() ==
"Invalid Sender with Connection") {
await CRUD().post(link: AppLink.updatePhoneInvalidSMSPassenger, payload: {
"phone_number":
'+2${Get.find<RegisterController>().phoneController.text}'
});
box.write(BoxName.phoneDriver,
'+2${Get.find<RegisterController>().phoneController.text}');
box.write(BoxName.isVerified, '1');
await Get.put(LoginController()).loginUsingCredentials(
box.read(BoxName.driverID).toString(),
box.read(BoxName.emailDriver).toString(),
);
} else {
Get.defaultDialog(
title: 'You will recieve code in sms message'.tr,
title: 'You will receive code in sms message'.tr,
middleText: '',
confirm: MyElevatedButton(
title: 'OK'.tr,

View File

@@ -5,6 +5,7 @@ import 'dart:math' as math;
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';
@@ -739,7 +740,10 @@ class MapPassengerController extends GetxController {
var res = await CRUD().get(
link: AppLink.getRideStatusFromStartApp,
payload: {'passenger_id': box.read(BoxName.passengerID)});
if (res == 'failure') {}
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';
@@ -968,12 +972,6 @@ class MapPassengerController extends GetxController {
}
}
// Example usage
void someFunction() {
String whatsAppLink = 'https://maps.google.com/maps?q=37.4220,-122.0841';
handleWhatsAppLink(whatsAppLink);
}
void goToWhatappLocation() async {
if (sosFormKey.currentState!.validate()) {
changeIsWhatsAppOrder(true);
@@ -999,7 +997,8 @@ class MapPassengerController extends GetxController {
late String make = '';
late String licensePlate = '';
confirmRideForFirstDriver() async {
await getCarsLocationByPassengerAndReloadMarker();
startCarLocationSearch(box.read(BoxName.carType));
// await getCarsLocationByPassengerAndReloadMarker();
await getNearestDriverByPassengerLocationAPIGOOGLE();
if (dataCarsLocationByPassenger != 'failure') {
@@ -1097,10 +1096,12 @@ class MapPassengerController extends GetxController {
box.read(BoxName.carType),
kazan.toStringAsFixed(0),
passengerRate.toStringAsFixed(2),
]; //
];
Log.print('body: ${body}');
FirebaseMessagesController().sendNotificationToDriverMAP(
'Order'.tr,
jsonDecode(value)['message'].toString(),
'from: $startNameAddress\nto: $startNameAddress\ndistanceFromMe: $distanceByPassenger\nDistance :$distance\nPrice ; $totalPassenger',
// jsonDecode(value)['message'].toString(),
dataCarsLocationByPassenger['message'][carsOrder]['token']
.toString(),
body,
@@ -1108,6 +1109,8 @@ class MapPassengerController extends GetxController {
// polylineCoordinates.toString()
);
Log.print(
'body: ${dataCarsLocationByPassenger['message'][carsOrder]['token']}');
});
delayAndFetchRideStatus(rideId);
if (shouldFetch == false) {
@@ -1135,12 +1138,13 @@ class MapPassengerController extends GetxController {
bool isDriversTokensSend = false;
confirmRideForAllDriverAvailable() async {
// isDriversTokensSend = true;
driversToken.remove(driverToken);
PaymentController paymentController = Get.find<PaymentController>();
rideConfirm = true;
shouldFetch = true;
isBottomSheetShown = false;
timeToPassengerFromDriverAfterApplied = 60;
driversToken.remove(driverToken);
List<String> body = [
'${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
'${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
@@ -1196,44 +1200,57 @@ class MapPassengerController extends GetxController {
update();
}
int tick = 0; // Move tick outside the function to maintain its state
void delayAndFetchRideStatus(String rideId) {
Timer(const Duration(seconds: 1), () async {
Timer.periodic(const Duration(seconds: 1), (timer) async {
if (shouldFetch) {
if (remainingTimeToPassengerFromDriverAfterApplied > 0) {
var res = await getRideStatus(rideId);
String res = await getRideStatus(rideId);
// var decod = jsonDecode(res);
if (res.toString() == 'Apply') {
// getUpdatedRideForDriverApply(rideId);
Log.print('tick: $tick');
if (res.toString() == 'waiting' && tick == 15) {
timer.cancel(); // Stop the current timer
delayAndFetchRideStatusForAllDriverAvailable(rideId);
} else if (res.toString() == 'Apply') {
timer.cancel(); // Stop the current timer
shouldFetch = false; // Stop further fetches
statusRide = 'Apply';
rideConfirm = false;
isSearchingWindow = false;
update();
startTimerFromDriverToPassengerAfterApplied();
// startTimer();
} else if (res.toString() == 'Refused') {
statusRide = 'Refused';
// isDriversTokensSend = false;
if (isDriversTokensSend == false) {
confirmRideForAllDriverAvailable();
isDriversTokensSend = true;
}
} // Start 15-second timer
} else if (isDriversTokensSend == false) {
delayAndFetchRideStatus(
rideId); // Repeat the delay and fetch operation
// No need to recall delayAndFetchRideStatus as Timer.periodic is already running
update();
}
tick++;
} else {
timer
.cancel(); // Stop the timer if remainingTimeToPassengerFromDriverAfterApplied <= 0
}
} else {
timer.cancel(); // Stop the timer if shouldFetch is false
}
});
}
void delayAndFetchRideStatusForAllDriverAvailable(String rideId) {
Timer(const Duration(milliseconds: 1000), () async {
if (shouldFetch) {
int attemptCounter = 0;
const int maxAttempts = 15;
void fetchRideStatus() async {
if (shouldFetch && attemptCounter < maxAttempts) {
attemptCounter++;
var res = await getRideStatus(rideId);
// var decod = jsonDecode(res);
if (res.toString() == 'Apply') {
getUpdatedRideForDriverApply(rideId);
@@ -1243,10 +1260,28 @@ class MapPassengerController extends GetxController {
isSearchingWindow = false;
update();
startTimerFromDriverToPassengerAfterApplied();
} else if (res.toString() == 'Refused') {
delayAndFetchRideStatusForAllDriverAvailable(rideId);
} else {
Timer(const Duration(seconds: 2),
fetchRideStatus); // Continue fetching for other statuses
}
} else {
// Stop fetching after maxAttempts or if shouldFetch is false
shouldFetch = false;
MyDialog().getDialog('upgrade price'.tr,
'You can upgrade price to may driver accept your order'.tr, () {
Get.back();
});
update();
print('Stopped fetching ride status after 30 seconds.');
}
}
fetchRideStatus(); // Initial call to start the process
}
void start15SecondTimer(String rideId) {
Timer(const Duration(seconds: 15), () {
delayAndFetchRideStatusForAllDriverAvailable(rideId);
});
}
@@ -1431,89 +1466,134 @@ class MapPassengerController extends GetxController {
Map<String, Timer> _animationTimers = {};
final int updateIntervalMs = 100; // Update every 100ms
final double minMovementThreshold =
1.0; // Minimum movement in meters to trigger update
10; // Minimum movement in meters to trigger update
Future<void> getCarsLocationByPassengerAndReloadMarker() async {
void startCarLocationSearch(String carType) {
int searchInterval = 5; // Interval in seconds
int boundIncreaseStep = 4500; // Initial bounds in meters
int maxAttempts = 3; // Maximum attempts to increase bounds
int attempt = 0; // Current attempt
Timer.periodic(Duration(seconds: searchInterval), (Timer timer) async {
if (attempt >= maxAttempts) {
timer.cancel();
noCarString = true;
dataCarsLocationByPassenger = 'failure';
update();
return;
}
bool foundCars = await getCarsLocationByPassengerAndReloadMarker(
carType, boundIncreaseStep);
if (foundCars) {
timer.cancel();
} else {
attempt++;
boundIncreaseStep = boundIncreaseStep + 1500; // Increase bounds
}
});
}
Future<bool> getCarsLocationByPassengerAndReloadMarker(
String carType, int boundIncreaseStep) async {
if (statusRide == 'wait') {
LatLngBounds bounds = calculateBounds(
passengerLocation.latitude, passengerLocation.longitude, 7000);
carsLocationByPassenger = [];
LatLngBounds bounds = calculateBounds(passengerLocation.latitude,
passengerLocation.longitude, boundIncreaseStep.toDouble());
var res;
var res = await _fetchCarLocations(bounds);
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 '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(),
});
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 = res;
// noCarString = true;
// dataCarsLocationByPassenger = res;
// update();
return false;
} else {
noCarString = false;
dataCarsLocationByPassenger = jsonDecode(res);
driverId = dataCarsLocationByPassenger['message'][carsOrder]
['driver_id']
.toString();
gender = dataCarsLocationByPassenger['message'][carsOrder]['gender']
.toString();
_updateMarkers(dataCarsLocationByPassenger['message']);
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']);
}
update();
return true;
}
update();
}
}
Future<String> _fetchCarLocations(LatLngBounds bounds) async {
var payload = {
'southwestLat': bounds.southwest.latitude.toString(),
'southwestLon': bounds.southwest.longitude.toString(),
'northeastLat': bounds.northeast.latitude.toString(),
'northeastLon': bounds.northeast.longitude.toString(),
};
String link;
switch (box.read(BoxName.carType)) {
case 'Lady':
link = AppLink.getFemalDriverLocationByPassenger;
break;
case 'Speed':
link = AppLink.getCarsLocationByPassengerSpeed;
break;
case 'Delivery':
link = AppLink.getCarsLocationByPassengerDelivery;
break;
default:
link = AppLink.getCarsLocationByPassenger;
}
return await CRUD().get(link: link, payload: payload);
}
void _updateMarkers(List<dynamic> carsData) {
driversToken.clear();
for (var json in carsData) {
String markerId = json['driver_id'].toString();
LatLng newPosition = LatLng(
double.parse(json['latitude']),
double.parse(json['longitude']),
);
double newHeading = double.parse(json['heading']);
BitmapDescriptor icon = _getIconForCar(json);
_updateOrCreateMarker(markerId, newPosition, newHeading, icon);
driversToken.add(json['token']);
}
// Remove markers for cars that are no longer present
markers.removeWhere((marker) => !carsData
.any((car) => car['driver_id'].toString() == marker.markerId.value));
return false;
}
BitmapDescriptor _getIconForCar(Map<String, dynamic> carData) {
if (carData['model'].toString().contains('دراجة')) {
return motoIcon;
} else if (carData['gender'] == 'Male'.tr) {
return carIcon;
} else {
} else if (carData['gender'] == 'Female') {
return ladyIcon;
} else {
return carIcon;
}
}
@@ -1611,6 +1691,8 @@ class MapPassengerController extends GetxController {
'sosPhone': sosPhonePassengerProfile.text,
},
);
box.write(
BoxName.sosPhonePassenger, sosPhonePassengerProfile.text);
}
}));
}
@@ -1714,12 +1796,12 @@ class MapPassengerController extends GetxController {
Future runEvery30SecondsUntilConditionMet() async {
// Calculate the duration of the trip in minutes.
double tripDurationInMinutes = durationToPassenger / 6;
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: 4));
await Future.delayed(const Duration(seconds: 5));
if (rideTimerBegin == true || statusRide == 'Apply') {
await getDriverCarsLocationToPassengerAfterApplied();
reloadMarkerDriverCarsLocationToPassengerAfterApplied();
@@ -1761,7 +1843,7 @@ class MapPassengerController extends GetxController {
}
void reloadMarkerDriverCarsLocationToPassengerAfterApplied() {
clearMarkersExceptStartEnd();
// clearMarkersExceptStartEnd();
LatLng driverPosition = LatLng(
double.parse(datadriverCarsLocationToPassengerAfterApplied['message'][0]
@@ -1780,9 +1862,9 @@ class MapPassengerController extends GetxController {
? motoIcon
: datadriverCarsLocationToPassengerAfterApplied['message'][0]
['gender'] ==
'Male'.tr
? carIcon
: ladyIcon;
'Female'
? ladyIcon
: carIcon;
_updateMarkerPosition(driverPosition, heading, icon);
}
@@ -1834,6 +1916,18 @@ class MapPassengerController extends GetxController {
update();
}
searchNewDriverAfterRejectingFromDriver() {
//
shouldFetch = true; // Stop further fetches
statusRide = 'wait';
rideConfirm = true;
isSearchingWindow = true;
confirmRideForFirstDriver();
update();
}
Future<void> cancelRideAfterRejectFromAll() async {
clearPlacesDestination();
clearPolyline();
@@ -1869,6 +1963,10 @@ class MapPassengerController extends GetxController {
"order_id": rideId.toString(), // Convert to String
"status": 'Cancel'
});
await CRUD().post(link: AppLink.updateRides, payload: {
"id": rideId.toString(), // Convert to String
"status": 'Cancel'
});
print('Cancel');
FirebaseMessagesController().sendNotificationToDriverMAP(
'Cancel Trip',
@@ -2169,7 +2267,7 @@ class MapPassengerController extends GetxController {
void addCustomCarIcon() {
ImageConfiguration config = ImageConfiguration(
size: const Size(30, 30), devicePixelRatio: Get.pixelRatio);
size: const Size(30, 35), devicePixelRatio: Get.pixelRatio);
BitmapDescriptor.asset(
config,
'assets/images/car.png',
@@ -2332,7 +2430,7 @@ class MapPassengerController extends GetxController {
startMarkerReloading() async {
int reloadCount = 0;
Timer.periodic(const Duration(seconds: 2), (timer) {
Timer.periodic(const Duration(seconds: 5), (timer) {
reloadCount++;
if (!rideConfirm) {
@@ -2348,11 +2446,13 @@ class MapPassengerController extends GetxController {
}
reloadMarkers() async {
if (statusRide == 'wait') {
clearMarkersExceptStartEnd();
await getCarsLocationByPassengerAndReloadMarker();
await getNearestDriverByPassengerLocation();
}
// if (statusRide == 'wait') {
clearMarkersExceptStartEnd();
// _smoothlyUpdateMarker();
startCarLocationSearch(box.read(BoxName.carType));
// await getCarsLocationByPassengerAndReloadMarker();
await getNearestDriverByPassengerLocation();
// }
}
String durationByPassenger = '';
@@ -2361,6 +2461,7 @@ class MapPassengerController extends GetxController {
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
@@ -2380,7 +2481,7 @@ class MapPassengerController extends GetxController {
double.parse(carLocation['latitude']),
double.parse(carLocation['longitude']),
);
durationToPassenger = (distance * 35 * (1000 / 3600))
durationToPassenger = (distance * 25 * (1000 / 3600))
.round(); //////35 is avg of speed in city
// Update the UI with the distance and duration
update();
@@ -2487,13 +2588,38 @@ class MapPassengerController extends GetxController {
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: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
Get.back();
},
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(
@@ -2528,7 +2654,8 @@ class MapPassengerController extends GetxController {
isLoading = true;
update();
remainingTime = 25; //to make cancel every call
await getCarsLocationByPassengerAndReloadMarker();
startCarLocationSearch(box.read(BoxName.carType));
// await getCarsLocationByPassengerAndReloadMarker();
var coordDestination = destination.split(',');
double latPassengerDestination = double.parse(coordDestination[0]);
double lngPassengerDestination = double.parse(coordDestination[1]);
@@ -2731,7 +2858,8 @@ class MapPassengerController extends GetxController {
getMapPoints(String originSteps, String destinationSteps, int index) async {
isWayPointStopsSheetUtilGetMap = false;
// haveSteps = true;
await getCarsLocationByPassengerAndReloadMarker();
startCarLocationSearch(box.read(BoxName.carType));
// await getCarsLocationByPassengerAndReloadMarker();
// isLoading = true;
update();
var url =

View File

@@ -44,11 +44,31 @@ class MyTranslation extends Translations {
"Choose who this order is for": "اختر لمن هذا الطلب",
"I want to order for myself": "أريد أن أطلب لنفسي",
"I want to order for someone else": "أريد أن أطلب لشخص آخر",
"Cancel Trip from driver": "إلغاء الرحلة من السائق",
"If you want order to another person": "إذا كنت تريد الطلب لشخص آخر",
"Wehaven'tfoundanydriversyet.Considerincreasingyourtripfeetomakeyouroffermoreattractivetodrivers.":
"We will look for a new driver.\nPlease wait.":
"سنبحث عن سائق جديد.\nمن فضلك انتظر.",
"upgrade price": "رفع السعر",
"You can upgrade price to may driver accept your order":
"يمكنك رفع السعر حتى يقبل السائق طلبك",
"No, I want to cancel this trip": "لا، أريد إلغاء هذه الرحلة",
'Trip Cancelled. The cost of the trip will be added to your wallet.':
"تم إلغاء الرحلة. سيتم إضافة تكلفة الرحلة إلى محفظتك.",
"Attention": "تنبيه",
"Trip Cancelled. The cost of the trip will be deducted from your wallet.":
"تم إلغاء الرحلة. سيتم خصم تكلفة الرحلة من محفظتك.",
"You will be charged for the cost of the driver coming to your location.":
"سيتم خصم تكلفة قدوم السائق إلى موقعك.",
"reject your order.": "رفض طلبك.",
"Order Under Review": "الطلب قيد المراجعة",
"is reviewing your order. They may need more information or a higher price.":
"يتم مراجعة طلبك. قد يحتاجون إلى مزيد من المعلومات أو سعر أعلى.",
"The driver canceled your ride.": "ألغى السائق رحلتك.",
"We haven't found any drivers yet. Consider increasing your trip fee to make your offer more attractive to drivers.":
"لم نجد أي سائقين بعد. ضع في اعتبارك زيادة رسوم رحلتك لجعل عرضك أكثر جاذبية للسائقين.",
"IncreaseYourTripFee(Optional)": "زيادة رسوم رحلتك (اختياري)",
"Increase Your Trip Fee (Optional)": "زيادة رسوم رحلتك (اختياري)",
'Vibration': "اهتزاز‏",
'Resend code': "إعادة إرسال الرمز",
"Sign in with Apple": "تسجيل الدخول باستخدام Apple",

View File

@@ -1,8 +1,10 @@
import 'dart:convert';
import 'package:SEFER/constant/api_key.dart';
import 'package:SEFER/constant/style.dart';
import 'package:SEFER/controller/firebase/firbase_messge.dart';
import 'package:SEFER/controller/functions/tts.dart';
import 'package:SEFER/controller/payment/paymob/paymob_response.dart';
import 'package:SEFER/views/home/map_page_passenger.dart';
import 'package:SEFER/views/widgets/elevated_btn.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
@@ -101,6 +103,54 @@ class PaymentController extends GetxController {
});
}
payToDriverForCancelAfterAppliedAndHeNearYou(String rideId) async {
{
double costOfWaiting5Minute = box.read(BoxName.countryCode) == 'Egypt'
? (4 * .08) + (5 * 1)
// 4 indicate foe 4 km ditance from driver start move to passenger
: (4 * .06) + (5 * .06); //for Eygpt other like jordan .06 per minute
var paymentTokenWait =
await generateTokenDriver(costOfWaiting5Minute.toString());
var res = await CRUD().post(link: AppLink.addDrivePayment, payload: {
'rideId': rideId,
'amount': costOfWaiting5Minute.toString(),
'payment_method': 'cancel-from-near',
'passengerID': box.read(BoxName.passengerID).toString(),
'token': paymentTokenWait,
'driverID': Get.find<MapPassengerController>().driverId.toString(),
});
var paymentTokenWait1 =
await generateTokenDriver(costOfWaiting5Minute.toString());
var res1 =
await CRUD().post(link: AppLink.addDriversWalletPoints, payload: {
'paymentID': 'rideId$rideId',
'amount': (costOfWaiting5Minute).toStringAsFixed(0),
'paymentMethod': 'cancel-from-near',
'token': paymentTokenWait1,
'driverID': Get.find<MapPassengerController>().driverId.toString(),
});
if (res != 'failure') {
FirebaseMessagesController().sendNotificationToDriverMAP(
'Cancel',
'Trip Cancelled. The cost of the trip will be added to your wallet.'
.tr,
Get.find<MapPassengerController>().driverToken,
[],
'cancel.wav',
);
}
var paymentTokenWaitPassenger1 =
await generateTokenPassenger((costOfWaiting5Minute * -1).toString());
await CRUD().post(link: AppLink.addPassengersWallet, payload: {
'passenger_id': box.read(BoxName.passengerID).toString(),
'balance': (costOfWaiting5Minute * -1).toString(),
'token': paymentTokenWaitPassenger1,
});
Get.offAll(const MapPagePassenger());
}
}
addPassengerWallet() async {
isLoading = true;
update();

View File

@@ -6,6 +6,7 @@ import 'package:url_launcher/url_launcher.dart';
import '../../constant/api_key.dart';
import '../../main.dart';
import '../../print.dart';
class PaymobManager extends GetxController {
String authanticationToken1 = "";
@@ -95,6 +96,7 @@ class PaymobManager extends GetxController {
'username': AK.usernamePayMob,
"password": AK.passwordPayMob,
});
Log.print('token: ${response}');
return response.data["token"];
}
@@ -111,6 +113,7 @@ class PaymobManager extends GetxController {
"delivery_needed": "false",
"items": [],
});
Log.print('id: ${response}');
return response.data["id"];
}
@@ -126,16 +129,15 @@ class PaymobManager extends GetxController {
"auth_token": authanticationToken.toString(),
"order_id": orderId.toString(),
"integration_id":
4556056, ////todo wallet or online card int.parse(AK.integrationIdPayMob),
4601103, ////todo wallet or online card int.parse(AK.integrationIdPayMob),
"lock_order_when_paid": "false",
"amount_cents": amount,
"currency": currency,
"billing_data": {
"first_name": box.read(BoxName.nameDriver) ?? box.read(BoxName.name),
"last_name": box.read(BoxName.lastNameDriver) ?? box.read(BoxName.name),
"email": box.read(BoxName.emailDriver) ?? box.read(BoxName.email),
"phone_number":
box.read(BoxName.phoneDriver) ?? box.read(BoxName.phone),
"first_name": box.read(BoxName.name),
"last_name": box.read(BoxName.name),
"email": box.read(BoxName.email),
"phone_number": box.read(BoxName.phone),
"apartment": "NA",
"floor": "NA",
"street": "NA",
@@ -147,7 +149,7 @@ class PaymobManager extends GetxController {
"state": "NA"
},
});
Log.print('token: ${response}');
return response.data["token"];
}
}

View File

@@ -4,6 +4,8 @@ import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import '../../../print.dart';
class PaymobResponseWallet {
final bool success;
final String? transactionID;
@@ -142,9 +144,7 @@ class PaymobPaymentWallet {
}) async {
final Map<String, dynamic> data = {
"source": {
"identifier": box
.read(BoxName.phone)
.toString(), // Replace with actual source identifier
"identifier": box.read(BoxName.phone).toString(),
"subtype": "WALLET",
},
"payment_token": paymentToken,
@@ -219,6 +219,7 @@ class PaymobPaymentWallet {
),
);
final urlWallet = await _getWalletUrl(paymentToken: purchaseToken);
Log.print('urlWallet: ${urlWallet}');
if (context.mounted) {
final response = await PaymobIFrameWallet.show(