Update: 2026-06-25 02:28:33

This commit is contained in:
Hamza-Ayed
2026-06-25 02:28:33 +03:00
parent 1ff13f09ac
commit 98a8a2ae3d
43 changed files with 992 additions and 812 deletions

View File

@@ -300,8 +300,7 @@ class LoginController extends GetxController {
if (decoded is! Map || decoded.isEmpty) return;
if (decoded['status'] == 'failure' || decoded['status'] == 'Failure') {
Get.snackbar("User does not exist.".tr, '',
backgroundColor: Colors.red);
mySnackeBarError("User does not exist.".tr);
return;
}
@@ -445,7 +444,7 @@ class LoginController extends GetxController {
Get.offAll(() => const MapPagePassenger());
} catch (e) {
addError('$e', 'loginUsingCredentials');
Get.snackbar('Error', e.toString(), backgroundColor: Colors.redAccent);
mySnackeBarError(e.toString());
} finally {
isloading = false;
update();

View File

@@ -14,6 +14,7 @@ import 'package:siro_rider/constant/style.dart';
import 'package:siro_rider/controller/functions/crud.dart';
import 'package:siro_rider/views/auth/login_page.dart';
import 'package:siro_rider/views/widgets/elevated_btn.dart';
import 'package:siro_rider/views/widgets/error_snakbar.dart';
import '../../constant/box_name.dart';
import '../../main.dart';
@@ -145,13 +146,10 @@ class RegisterController extends GetxController {
},
);
if (responseChecker != 'failure') {
var data = jsonDecode(responseChecker);
if (responseChecker is Map) {
// If the phone number is already verified
if (data['message'][0]['verified'].toString() == '1') {
Get.snackbar('Phone number is verified before'.tr, '',
backgroundColor: AppColor.greenColor);
if (responseChecker['message'][0]['verified'].toString() == '1') {
mySnackbarSuccess('Phone number is verified before'.tr);
box.write(BoxName.isVerified, '1');
box.write(BoxName.phone, (phoneNumber));
Get.offAll(const MapPagePassenger());
@@ -310,22 +308,17 @@ class RegisterController extends GetxController {
box.read(BoxName.email).toString(),
);
} else {
Get.snackbar('Error'.tr,
"The email or phone number is already registered.".tr,
backgroundColor: Colors.redAccent);
mySnackeBarError("The email or phone number is already registered.".tr);
}
} else {
Get.snackbar('Error'.tr, "phone not verified".tr,
backgroundColor: Colors.redAccent);
mySnackeBarError("phone not verified".tr);
}
} else {
Get.snackbar('Error'.tr, "you must insert token code".tr,
backgroundColor: AppColor.redColor);
mySnackeBarError("you must insert token code".tr);
}
} catch (e) {
addError(e.toString(), 'passenger sign up ');
Get.snackbar('Error'.tr, "Something went wrong. Please try again.".tr,
backgroundColor: Colors.redAccent);
mySnackeBarError("Something went wrong. Please try again.".tr);
}
}
@@ -334,8 +327,7 @@ class RegisterController extends GetxController {
'email': emailController.text,
'token': verifyCode.text,
});
var dec = jsonDecode(res);
if (dec['status'] == 'success') {
if (res['status'] == 'success') {
Get.offAll(() => LoginPage());
}
}
@@ -352,7 +344,7 @@ class RegisterController extends GetxController {
'site': siteController.text,
'birthdate': birthDate,
});
if (jsonDecode(res)['status'] == 'success') {
if (res['status'] == 'success') {
int randomNumber = Random().nextInt(100000) + 1;
await CRUD().post(link: AppLink.sendVerifyEmail, payload: {
'email': emailController.text,

View File

@@ -5,6 +5,7 @@ import 'package:siro_rider/constant/links.dart';
import 'package:siro_rider/controller/functions/crud.dart';
import 'package:siro_rider/main.dart';
import 'package:get/get.dart';
import 'package:siro_rider/views/widgets/error_snakbar.dart';
import '../../print.dart';
import '../../views/home/map_page_passenger.dart';
@@ -68,10 +69,10 @@ class OtpVerificationController extends GetxController {
isLoading.value = true;
// بإمكانك عرض رسالة نجاح هنا
} else {
Get.snackbar('Error'.tr, 'Failed to send OTP'.tr);
mySnackeBarError('Failed to send OTP'.tr);
}
} catch (e) {
Get.snackbar('Error', e.toString());
mySnackeBarError(e.toString());
} finally {
// isLoading.value = false;
}
@@ -107,10 +108,10 @@ class OtpVerificationController extends GetxController {
Get.offAll(() => const MapPagePassenger());
} else {
Get.snackbar('Verification Failed', 'OTP is incorrect or expired');
mySnackeBarError('OTP is incorrect or expired');
}
} catch (e) {
Get.snackbar('Error', e.toString());
mySnackeBarError(e.toString());
} finally {
isVerifying.value = false;
}

View File

@@ -2,6 +2,7 @@ import 'dart:convert';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:siro_rider/views/widgets/error_snakbar.dart';
import '../../constant/box_name.dart';
import '../../constant/links.dart';
@@ -32,7 +33,7 @@ class TokenController extends GetxController {
update();
var jsonToken = jsonDecode(res.body);
if (jsonToken['status'] == 'The token has been updated successfully.') {
Get.snackbar('token updated'.tr, '');
mySnackbarInfo('token updated'.tr);
}
}
}

View File

@@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:siro_rider/controller/functions/toast.dart';
import 'package:siro_rider/views/widgets/elevated_btn.dart';
import 'package:siro_rider/views/widgets/error_snakbar.dart';
import '../../constant/box_name.dart';
import '../../constant/colors.dart';
@@ -574,26 +575,9 @@ class FirebaseMessagesController extends GetxController {
// }
// }
SnackbarController driverAppliedTripSnakBar() {
return Get.snackbar(
'Driver Applied the Ride for You'.tr,
'',
colorText: AppColor.greenColor,
duration: const Duration(seconds: 3),
snackPosition: SnackPosition.TOP,
titleText: Text(
'Applied'.tr,
style: TextStyle(color: AppColor.redColor),
),
messageText: Text(
'Driver Applied the Ride for You'.tr,
style: AppStyle.title,
),
icon: Icon(Icons.approval, color: AppColor.primaryColor),
shouldIconPulse: true,
margin: const EdgeInsets.all(16),
padding: const EdgeInsets.all(16),
);
SnackbarController? driverAppliedTripSnakBar() {
mySnackbarInfo('Driver Applied the Ride for You'.tr);
return null;
}
Future<dynamic> passengerDialog(String message) {

View File

@@ -304,7 +304,8 @@ class CRUD {
Future sendWhatsAppAuth(String to, String token) async {
var res = await CRUD()
.get(link: AppLink.getApiKey, payload: {'keyName': 'whatsapp_key'});
var accesstoken = jsonDecode(res)['message']['whatsapp_key'];
if (res is! Map) return;
var accesstoken = res['message']['whatsapp_key'];
var headers = {
'Authorization': 'Bearer $accesstoken',
'Content-Type': 'application/json'

View File

@@ -10,6 +10,7 @@ import 'package:siro_rider/main.dart';
import 'package:siro_rider/onbording_page.dart';
import 'package:siro_rider/views/widgets/elevated_btn.dart';
import 'package:siro_rider/views/widgets/my_textField.dart';
import 'package:siro_rider/views/widgets/error_snakbar.dart';
import '../../constant/style.dart';
import 'package:siro_rider/controller/home/map/map_socket_controller.dart';
@@ -30,8 +31,7 @@ class LogOutController extends GetxController {
Future deleteMyAccountDriver(String id) async {
await CRUD().post(link: AppLink.removeUser, payload: {'id': id}).then(
(value) => Get.snackbar('Deleted'.tr, 'Your Account is Deleted',
backgroundColor: AppColor.redColor));
(value) => mySnackbarSuccess('Your Account is Deleted'.tr));
}
checkBeforeDelete() async {
@@ -198,9 +198,7 @@ class LogOutController extends GetxController {
'email': box.read(BoxName.email),
});
} else {
Get.snackbar('Email Wrong'.tr, 'Email you inserted is Wrong.'.tr,
snackPosition: SnackPosition.BOTTOM,
backgroundColor: AppColor.redColor);
mySnackeBarError('Email you inserted is Wrong.'.tr);
}
}
}

View File

@@ -58,7 +58,7 @@ class AppInitializer {
var res =
await CRUD().get(link: AppLink.getapiKey, payload: {"keyName": key1});
if (res != 'failure') {
var d = jsonDecode(res)['message'];
var d = res['message'];
storage.write(key: key1, value: d[key1].toString());
} else {}
}
@@ -69,7 +69,7 @@ class AppInitializer {
var res =
await CRUD().get(link: AppLink.getLocationAreaLinks, payload: {});
if (res != 'failure') {
links = List<Map<String, dynamic>>.from(jsonDecode(res)['message']);
links = List<Map<String, dynamic>>.from(res['message']);
await box.remove(BoxName.locationName);
await box.remove(BoxName.basicLink);
await box.remove(links[4]['name']);

View File

@@ -20,7 +20,7 @@ class SmsEgyptController extends GetxController {
Future<String> getSender() async {
var res = await CRUD().get(link: AppLink.getSender, payload: {});
if (res != 'failure') {
var d = jsonDecode(res)['message'][0]['senderId'].toString();
var d = res['message'][0]['senderId'].toString();
return d;
} else {
return "Sefer Egy";

View File

@@ -8,6 +8,7 @@ import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart';
import 'package:secure_string_operations/secure_string_operations.dart';
import 'package:siro_rider/views/widgets/error_snakbar.dart';
import '../../constant/box_name.dart';
import '../../constant/char_map.dart';
@@ -54,8 +55,7 @@ class ImageController extends GetxController {
link,
);
} catch (e) {
Get.snackbar('Image Upload Failed'.tr, e.toString(),
backgroundColor: AppColor.redColor);
mySnackeBarError(e.toString());
} finally {
isloading = false;
update();

View File

@@ -29,7 +29,7 @@ class BlinkingController extends GetxController {
},
));
}
var decode = jsonDecode(value);
var decode = value;
// if (decode["status"] == "success") {
// var firstElement = decode["message"][0];

View File

@@ -303,21 +303,7 @@ class LocationSearchController extends GetxController {
rideLifecycle.resetNoRideSearch();
}
final bool isLoggedIn = box.read(BoxName.isVerified) == '1' &&
box.read(BoxName.passengerID) != null;
if (isLoggedIn) {
try {
getReverseGeocoding(passengerLocation).then((address) {
currentLocationString = address;
update();
});
} catch (e) {
Log.print('Error resolving current location: $e');
}
} else {
Log.print('LocationSearchController: Skipping reverse geocoding call, user not logged in.');
}
Log.print('LocationSearchController: Reverse geocoding deferred — will run when map is idle.');
OfflineMapService.instance
.downloadRegion(passengerLocation, radiusKm: 10.0);
@@ -493,10 +479,22 @@ class LocationSearchController extends GetxController {
}
}
bool _pendingGeocode = true;
void updateCurrentLocationFromCamera(LatLng target) {
Log.print('📍 updateCurrentLocationFromCamera: $target');
newMyLocation = target;
if (_pendingGeocode) {
_pendingGeocode = false;
if (box.read(BoxName.isVerified) == '1') {
getReverseGeocoding(target).then((address) {
currentLocationString = address;
update();
});
}
}
if (startLocationFromMap == true) {
Log.print('📍 Updating startLocationFromMap to $target');
newStartPointLocation = target;
@@ -865,12 +863,7 @@ class LocationSearchController extends GetxController {
mapEngine.heightBottomSheetShown = 250;
update();
Get.snackbar(
'Location Received'.tr,
'Route and prices have been calculated successfully!'.tr,
backgroundColor: AppColor.greenColor,
colorText: Colors.white,
);
mySnackbarInfo('Route and prices have been calculated successfully!'.tr);
}
} else {
Log.print('⚠️ Could not extract valid coordinates from link: $link');

View File

@@ -49,7 +49,7 @@ class NearbyDriversController extends GetxController {
},
);
if (res == 'failure') {
if (res == 'failure' || res is! Map) {
noCarString = true;
dataCarsLocationByPassenger = 'failure';
update();
@@ -57,7 +57,7 @@ class NearbyDriversController extends GetxController {
}
noCarString = false;
var responseData = jsonDecode(res);
var responseData = res;
dataCarsLocationByPassenger = responseData;
List driversList = [];

View File

@@ -1253,15 +1253,14 @@ class RideLifecycleController extends GetxController {
'data': {'status': 'NoRide', 'needsReview': false}
};
isStartAppHasRide = false;
} else {
var decoded = jsonDecode(res);
if (decoded['status'] == 'failure') {
} else if (res is Map) {
if (res['status'] == 'failure') {
rideStatusFromStartApp = {
'data': {'status': 'NoRide', 'needsReview': false}
};
isStartAppHasRide = false;
} else {
rideStatusFromStartApp = decoded;
rideStatusFromStartApp = res;
}
}
@@ -1654,13 +1653,12 @@ class RideLifecycleController extends GetxController {
payload: {'passengerID': box.read(BoxName.passengerID).toString()});
if (res != 'failure') {
var response = jsonDecode(res);
Log.print('getUpdatedRideForDriverApply Response: $response');
Log.print('getUpdatedRideForDriverApply Response: $res');
if (response['status'] == 'success' &&
response['data'] != null &&
response['data'] is Map) {
var data = response['data'];
if (res['status'] == 'success' &&
res['data'] != null &&
res['data'] is Map) {
var data = res['data'];
driverId = data['driver_id']?.toString() ?? '';
driverPhone = data['phone']?.toString() ?? '';
@@ -1814,10 +1812,9 @@ class RideLifecycleController extends GetxController {
'country': box.read(BoxName.countryCode) ?? '',
});
if (res != 'failure') {
var response = jsonDecode(res);
if (response['status'] == 'success') {
var data = response['data'];
if (res is Map) {
if (res['status'] == 'success') {
var data = res['data'];
totalPassengerSpeed = data['totalPassengerSpeed']?.toString() ?? '0';
totalPassengerBalash =
data['totalPassengerBalash']?.toString() ?? '0';
@@ -1847,7 +1844,7 @@ class RideLifecycleController extends GetxController {
} else {
MyDialog().getDialog(
'Promo Error'.tr,
response['message']?.toString() ?? 'Invalid Promo'.tr,
res['message']?.toString() ?? 'Invalid Promo'.tr,
() => Get.back());
return;
}
@@ -1855,8 +1852,7 @@ class RideLifecycleController extends GetxController {
Get.back();
await Future.delayed(const Duration(milliseconds: 120));
} catch (e) {
Get.snackbar('Error'.tr, e.toString(),
backgroundColor: AppColor.redColor);
mySnackeBarError(e.toString());
}
}
@@ -1891,10 +1887,9 @@ class RideLifecycleController extends GetxController {
'country': box.read(BoxName.countryCode) ?? '',
});
if (res != 'failure') {
var response = jsonDecode(res);
if (response['status'] == 'success') {
var data = response['data'];
if (res is Map) {
if (res['status'] == 'success') {
var data = res['data'];
totalPassengerSpeed = data['totalPassengerSpeed']?.toString() ?? '0';
totalPassengerBalash =
data['totalPassengerBalash']?.toString() ?? '0';
@@ -1914,7 +1909,7 @@ class RideLifecycleController extends GetxController {
data['totalPassengerRayehGaiBalash']?.toString() ?? '0';
// Save price_token from server response
priceToken = response['price_token']?.toString() ?? '';
priceToken = res['price_token']?.toString() ?? '';
totalPassenger = totalPassengerSpeed;
totalCostPassenger = totalPassenger;
@@ -2194,12 +2189,10 @@ class RideLifecycleController extends GetxController {
link: AppLink.getDriverCarsLocationToPassengerAfterApplied,
payload: {'driver_id': driverId});
if (res != 'failure') {
var datadriverLocation = jsonDecode(res);
if (datadriverLocation['message'] != null &&
datadriverLocation['message'].isNotEmpty) {
var _data = datadriverLocation['message'][0];
if (res != 'failure' && res is Map) {
if (res['message'] != null &&
(res['message'] as List).isNotEmpty) {
var _data = (res['message'] as List)[0];
LatLng newDriverPos = LatLng(
double.parse(_data['latitude'].toString()),
@@ -2233,7 +2226,7 @@ class RideLifecycleController extends GetxController {
}
mapEngine.clearMarkersExceptStartEndAndDriver();
reloadMarkerDriverCarsLocationToPassengerAfterApplied(
datadriverLocation);
res);
}
}
update();
@@ -2641,8 +2634,7 @@ class RideLifecycleController extends GetxController {
throw Exception('Failed to save trip');
}
} catch (e) {
Get.snackbar('Error'.tr, 'Failed to book trip: $e'.tr,
backgroundColor: AppColor.redColor);
mySnackeBarError('Failed to book trip: $e'.tr);
}
}
@@ -3639,21 +3631,14 @@ class RideLifecycleController extends GetxController {
Future<void> cancelRide() async {
if (selectedReasonIndex == -1) {
Get.snackbar(
'Attention'.tr,
'Please select a reason first'.tr,
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.orange,
colorText: Colors.white,
);
mySnackbarWarning('Please select a reason first'.tr);
return;
}
String finalReason = selectedReasonText;
if (finalReason == "Other".tr) {
if (otherReasonController.text.trim().isEmpty) {
Get.snackbar("Attention".tr, "Please write the reason...".tr,
backgroundColor: Colors.red, colorText: Colors.white);
mySnackbarWarning("Please write the reason...".tr);
return;
}
finalReason = otherReasonController.text.trim();
@@ -3697,8 +3682,7 @@ class RideLifecycleController extends GetxController {
var res =
await CRUD().get(link: AppLink.getapiKey, payload: {"keyName": key});
if (res != 'failure') {
var d = jsonDecode(res)['message'];
return d[key].toString();
return res['message'][key].toString();
}
return null;
}
@@ -3709,7 +3693,7 @@ class RideLifecycleController extends GetxController {
payload: {'id': rideId});
Log.print(response);
Log.print('2176');
return jsonDecode(response)['data'];
return response['data'];
}
void handleActiveRideOnStartup(dynamic data) {
@@ -4365,11 +4349,10 @@ class RideLifecycleController extends GetxController {
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'];
if (resPromo is Map) {
promo = resPromo['message']['promo_code'];
discount = resPromo['message']['amount'];
validity = resPromo['message']['validity_end_date'];
}
box.write(BoxName.isFirstTime, '1');
Get.dialog(

View File

@@ -15,6 +15,7 @@ import '../../../print.dart';
import '../../../services/emergency_signal_service.dart';
import '../../../views/widgets/elevated_btn.dart';
import '../../../views/widgets/my_textField.dart';
import '../../../views/widgets/error_snakbar.dart';
import '../../functions/launch.dart';
import '../../firebase/notification_service.dart';
import '../../functions/crud.dart';
@@ -255,7 +256,7 @@ class UiInteractionsController extends GetxController {
String storedPhone = box.read(BoxName.sosPhonePassenger)!;
if (rideLifecycle.rideId == 'yet' || rideLifecycle.driverId.isEmpty) {
Get.snackbar("Alert".tr, "Wait for the trip to start first".tr);
mySnackbarWarning("Wait for the trip to start first".tr);
return;
}
@@ -374,8 +375,7 @@ Siro Team''';
} else if (res['status'] == 'success') {
if (Get.isDialogOpen ?? false) Get.back();
Get.snackbar("Success".tr, "The invitation was sent successfully".tr,
backgroundColor: AppColor.greenColor, colorText: Colors.white);
mySnackbarSuccess("The invitation was sent successfully".tr);
List tokensData = res['data'];
for (var device in tokensData) {

View File

@@ -88,7 +88,7 @@ class CaptainWalletController extends GetxController {
'amount': amount.toString(),
'payment_method': paymentMethod.toString(),
});
var d = jsonDecode(res);
var d = res;
paymentID = d['message'].toString();
}

View File

@@ -9,6 +9,7 @@ import 'package:siro_rider/constant/colors.dart';
import 'package:siro_rider/constant/links.dart';
import 'package:siro_rider/controller/functions/crud.dart';
import 'package:siro_rider/main.dart';
import 'package:siro_rider/views/widgets/error_snakbar.dart';
import 'package:http_parser/http_parser.dart';
import 'package:mime/mime.dart';
@@ -39,26 +40,11 @@ class ComplaintController extends GetxController {
// --- دالة مخصصة لعرض إشعارات Snackbar بشكل جميل ---
void _showCustomSnackbar(String title, String message,
{bool isError = false}) {
Get.snackbar(
'', // العنوان سيتم التعامل معه عبر titleText
'', // الرسالة سيتم التعامل معها عبر messageText
titleText: Text(title.tr,
style: const TextStyle(
color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16)),
messageText: Text(message.tr,
style: const TextStyle(color: Colors.white, fontSize: 14)),
backgroundColor: isError
? AppColor.redColor.withOpacity(0.95)
: const Color.fromARGB(255, 6, 148, 79).withOpacity(0.95),
icon: Icon(isError ? Icons.error_outline : Icons.check_circle_outline,
color: Colors.white, size: 28),
borderRadius: 12,
margin: const EdgeInsets.all(15),
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 18),
snackPosition: SnackPosition.BOTTOM,
duration: const Duration(seconds: 4),
colorText: Colors.white,
);
if (isError) {
mySnackeBarError(message.tr);
} else {
mySnackbarSuccess(message.tr);
}
}
// --- هذه الدالة تبقى كما هي لجلب بيانات الرحلة ---
@@ -69,7 +55,7 @@ class ComplaintController extends GetxController {
'passengerId': box.read(BoxName.passengerID).toString(),
});
if (res != 'failure') {
var d = jsonDecode(res)['message'];
var d = res['message'];
feedBack = d;
}
isLoading = false;

View File

@@ -1,8 +1,7 @@
import 'dart:convert';
import 'package:siro_rider/constant/box_name.dart';
import 'package:siro_rider/constant/colors.dart';
import 'package:siro_rider/constant/links.dart';
import 'package:siro_rider/controller/functions/country_logic.dart';
import 'package:siro_rider/controller/functions/crud.dart';
import 'package:flutter/material.dart';
import 'package:flutter_contacts/flutter_contacts.dart';
@@ -77,9 +76,8 @@ ${AppLink.inviteRedirectUrl}?code=$couponCode&app=rider
var response = await CRUD().get(link: AppLink.getInviteDriver, payload: {
"driverId": box.read(BoxName.driverID),
});
if (response != 'failure') {
var data = jsonDecode(response);
driverInvitationData = data['message'];
if (response != 'failure' && response is Map) {
driverInvitationData = response['message'];
update();
}
} catch (e) {
@@ -93,9 +91,8 @@ ${AppLink.inviteRedirectUrl}?code=$couponCode&app=rider
.get(link: AppLink.getDriverInvitationToPassengers, payload: {
"driverId": box.read(BoxName.passengerID),
});
if (response != 'failure') {
var data = jsonDecode(response);
driverInvitationDataToPassengers = data['message'];
if (response != 'failure' && response is Map) {
driverInvitationDataToPassengers = response['message'];
update();
}
} catch (e) {
@@ -167,17 +164,14 @@ ${AppLink.inviteRedirectUrl}?code=$couponCode&app=rider
// snackPosition: SnackPosition.BOTTOM);
}
} else {
Get.snackbar('No contacts found'.tr,
'No contacts with phone numbers were found on your device.'.tr);
mySnackbarWarning('No contacts with phone numbers were found on your device.'.tr);
}
} else {
Get.snackbar('Permission denied'.tr,
'Contact permission is required to pick contacts'.tr);
mySnackbarWarning('Contact permission is required to pick contacts'.tr);
}
} catch (e) {
Log.print('Error picking contacts: $e');
Get.snackbar(
'Error'.tr, 'An error occurred while picking contacts: $e'.tr);
mySnackeBarError('An error occurred while picking contacts: $e'.tr);
}
}
@@ -187,28 +181,11 @@ ${AppLink.inviteRedirectUrl}?code=$couponCode&app=rider
Get.back();
}
/// **IMPROVEMENT**: A new robust function to format phone numbers specifically for Syria (+963).
/// It handles various user inputs gracefully to produce a standardized international format.
String _formatSyrianPhoneNumber(String phone) {
// 1. Remove all non-digit characters to clean the input.
String digitsOnly = phone.replaceAll(RegExp(r'\D'), '');
// 2. If it already starts with the country code, we assume it's correct.
if (digitsOnly.startsWith('963')) {
return '$digitsOnly';
}
// 3. If it starts with '09' (common local format), remove the leading '0'.
if (digitsOnly.startsWith('09')) {
digitsOnly = digitsOnly.substring(1);
}
// 4. Prepend the Syrian country code.
return '963$digitsOnly';
/// Formats phone number based on the current country (Syria=963, Jordan=962, Egypt=20).
String _formatPhoneByCountry(String phone) {
return CountryLogic.formatCurrentCountryPhone(phone);
}
/// **IMPROVEMENT**: This method now uses the new phone formatting logic and
/// sends a much-improved, user-friendly WhatsApp message.
void sendInviteToPassenger() async {
if (invitePhoneController.text.isEmpty ||
invitePhoneController.text.length < 9) {
@@ -217,9 +194,8 @@ ${AppLink.inviteRedirectUrl}?code=$couponCode&app=rider
}
try {
// Use the new formatting function to ensure the number is correct.
String formattedPhoneNumber =
_formatSyrianPhoneNumber(invitePhoneController.text);
_formatPhoneByCountry(invitePhoneController.text);
var response =
await CRUD().post(link: AppLink.addInvitationPassenger, payload: {
@@ -229,13 +205,9 @@ ${AppLink.inviteRedirectUrl}?code=$couponCode&app=rider
if (response != 'failure' && response is Map) {
var d = response;
Get.snackbar('Success'.tr, 'Invite sent successfully'.tr,
backgroundColor: Colors.green, colorText: Colors.white);
mySnackbarSuccess('Invite sent successfully'.tr);
// التحقق الديناميكي من مكان البيانات (V1 vs V3)
var payload = d['data'] ?? d['message'];
// إذا كان الـ message نصاً وليس خريطة (Map)، نأخذ البيانات من المستوى الأعلى
if (payload is String) {
payload = d;
}
@@ -243,7 +215,6 @@ ${AppLink.inviteRedirectUrl}?code=$couponCode&app=rider
String expirationTime = (payload['expirationTime'] ?? '').toString();
String inviteCode = (payload['inviteCode'] ?? '').toString();
// New and improved WhatsApp message for better user engagement.
String message =
"👋 ${'Hello! I\'m inviting you to try Siro.'.tr}\n\n"
"🎁 ${'Use my invitation code to get a special gift on your first ride!'.tr}\n\n"
@@ -259,16 +230,11 @@ ${AppLink.inviteRedirectUrl}?code=$couponCode&app=rider
invitePhoneController.clear();
update();
} else {
Get.snackbar(
'Error'.tr, "This phone number has already been invited.".tr,
backgroundColor: AppColor.redColor,
duration: const Duration(seconds: 4));
mySnackbarWarning("This phone number has already been invited.".tr);
}
} catch (e) {
Log.print("Error sending invite: $e");
Get.snackbar(
'Error'.tr, 'An unexpected error occurred. Please try again.'.tr,
backgroundColor: AppColor.redColor);
mySnackeBarError('An unexpected error occurred. Please try again.'.tr);
}
}
@@ -314,9 +280,8 @@ ${AppLink.inviteRedirectUrl}?code=$couponCode&app=rider
},
);
if (response != 'failure') {
var data = jsonDecode(response);
if (data['status'] == 'success') {
if (response != 'failure' && response is Map) {
if (response['status'] == 'success') {
NotificationCaptainController().addNotificationCaptain(
invitation['passengerInviterId'].toString(),
"You have got a gift for invitation".tr,
@@ -325,7 +290,7 @@ ${AppLink.inviteRedirectUrl}?code=$couponCode&app=rider
);
fetchDriverStatsPassengers(); // Refresh list
} else {
Get.snackbar('Error'.tr, data['message'] ?? 'Claim failed'.tr, backgroundColor: AppColor.redColor);
mySnackeBarError(response['message'] ?? 'Claim failed'.tr);
}
}
},

View File

@@ -4,6 +4,7 @@ import 'package:siro_rider/constant/box_name.dart';
import 'package:siro_rider/constant/links.dart';
import 'package:siro_rider/controller/functions/crud.dart';
import 'package:siro_rider/main.dart';
import 'package:siro_rider/views/widgets/error_snakbar.dart';
class InvitesRewardsController extends GetxController {
bool isLoading = false;
@@ -70,20 +71,20 @@ class InvitesRewardsController extends GetxController {
}
);
Get.back(); // close loading
Navigator.maybeOf(Get.context!)?.pop(); // close loading dialog only
if (response != 'failure') {
if (response['status'] == 'success') {
Get.snackbar("Success".tr, "You have been successfully referred!".tr, backgroundColor: Colors.green, colorText: Colors.white);
mySnackbarSuccess("You have been successfully referred!".tr);
} else {
Get.snackbar("Notice".tr, response['message'] ?? "Could not add invite".tr);
mySnackbarWarning(response['message'] ?? "Could not add invite".tr);
}
} else {
Get.snackbar("Error".tr, "Network error occurred".tr);
mySnackeBarError("Network error occurred".tr);
}
} catch (e) {
Get.back(); // close loading
Get.snackbar("Error".tr, "Network error occurred".tr);
Navigator.maybeOf(Get.context!)?.pop(); // close loading dialog only
mySnackeBarError("Network error occurred".tr);
}
}
}

View File

@@ -30,7 +30,7 @@ class TripMonitorController extends GetxController {
var res = await CRUD().get(
link: AppLink.getLocationParents, payload: {"driver_id": driverId});
if (res != 'failure') {
tripData = jsonDecode(res);
tripData = res;
parentLocation = LatLng(
double.parse(tripData['message'][0]['latitude'].toString()),
double.parse(tripData['message'][0]['longitude'].toString()));

View File

@@ -53,9 +53,8 @@ class VipOrderController extends GetxController {
);
if (res != 'failure') {
var decodedResponse = jsonDecode(res);
if (decodedResponse['message'] is List) {
tripData.value = decodedResponse['message'];
if (res['message'] is List) {
tripData.value = res['message'];
} else {
tripData.clear(); // Ensure empty list if no data
// mySnackeBarError('No trip data found');

View File

@@ -31,7 +31,7 @@ class NotificationCaptainController extends GetxController {
Get.back();
}));
}
notificationData = jsonDecode(res);
notificationData = res;
// sql.insertData(notificationData['message'], TableName.captainNotification);
isLoading = false;

View File

@@ -26,11 +26,9 @@ class PassengerNotificationController extends GetxController {
Get.back();
});
} else {
final decoded = jsonDecode(res);
// التحقق من وجود البيانات في 'data' أو 'message'
var rawData = decoded['data'] ?? decoded['message'];
var rawData = res['data'] ?? res['message'];
if (decoded['status'] == 'error' || decoded['status'] == 'failure' || rawData == "No notification data found") {
if (res['status'] == 'error' || res['status'] == 'failure' || rawData == "No notification data found") {
notificationData = {'status': 'success', 'message': []}; // قائمة فارغة لمنع الخطأ في UI
} else {
// التأكد أننا نخزن قائمة

View File

@@ -14,7 +14,7 @@ class RideAvailableController extends GetxController {
isLoading = true;
var res = await CRUD().get(link: AppLink.getRideWaiting, payload: {});
if (res != 'failure') {
rideAvailableMap = jsonDecode(res);
rideAvailableMap = res;
isLoading = false;
update();
} else {

View File

@@ -30,7 +30,7 @@ class DriverWalletHistoryController extends GetxController {
},
));
}
archive = jsonDecode(res)['message'];
archive = res['message'];
isLoading = false;
update();
}

View File

@@ -16,6 +16,7 @@ import '../functions/crud.dart';
import 'paymob/e_cash_screen.dart';
import '../../views/home/my_wallet/payment_screen_mtn.dart';
import '../../views/home/my_wallet/payment_screen_cliq.dart';
import '../../views/widgets/error_snakbar.dart';
class PaymentController extends GetxController {
bool isLoading = false;
@@ -28,14 +29,14 @@ class PaymentController extends GetxController {
final walletphoneController = TextEditingController();
double totalPassenger = double.parse(
Get.find<RideLifecycleController>().totalPassenger.toString());
int? selectedAmount = 0;
double? selectedAmount = 0;
List<dynamic> totalPassengerWalletDetails = [];
String passengerTotalWalletAmount = '';
String ip = '1';
DateTime now = DateTime.now();
late int timestamp;
void updateSelectedAmount(int value) {
void updateSelectedAmount(double value) {
selectedAmount = value;
update();
}
@@ -80,8 +81,7 @@ class PaymentController extends GetxController {
'passengerId': box.read(BoxName.passengerID).toString(),
'amount': amount.toString(),
});
var d = jsonDecode(res);
return d['message'];
return res['message'];
}
Future<String> generateTokenDriver(String amount) async {
@@ -89,8 +89,7 @@ class PaymentController extends GetxController {
'driverID': Get.find<RideLifecycleController>().driverId,
'amount': amount.toString(),
});
var d = jsonDecode(res);
return d['message'];
return res['message'];
}
Future<void> payToDriverForCancelAfterAppliedAndHeNearYou(
@@ -430,14 +429,14 @@ class PaymentController extends GetxController {
Future<void> payWithClickWallet(BuildContext context, String amount, String currency) async {
try {
final phone = walletphoneController.text.trim();
final phone = box.read(BoxName.phoneWallet) ?? walletphoneController.text.trim();
if (phone.isEmpty) {
Get.defaultDialog(title: 'Error'.tr, content: Text('Please enter phone number'.tr));
mySnackeBarError('Please enter a phone number'.tr);
return;
}
Get.dialog(const Center(child: CircularProgressIndicator()), barrierDismissible: false);
var res = await CRUD().postWalletMtn(
link: AppLink.createCliqInvoice,
payload: {
@@ -447,9 +446,9 @@ class PaymentController extends GetxController {
"click_phone": phone,
},
);
Get.back(); // close loading
if (Get.isDialogOpen ?? false) Get.back();
late final Map<String, dynamic> resMap;
if (res is Map<String, dynamic>) {
resMap = res;
@@ -466,14 +465,11 @@ class PaymentController extends GetxController {
amount: double.parse(amount),
));
} else {
Get.defaultDialog(
title: 'Error'.tr,
content: Text(resMap['message']?.toString() ?? 'Failed to create invoice'.tr),
);
mySnackeBarError(resMap['message']?.toString() ?? 'Failed to create invoice'.tr);
}
} catch (e) {
if (Get.isDialogOpen ?? false) Get.back();
Get.defaultDialog(title: 'Error'.tr, content: Text(e.toString()));
mySnackeBarError(e.toString());
}
}

View File

@@ -48,7 +48,7 @@ class CaptainProfileController extends GetxController {
var res =
await CRUD().post(link: AppLink.updateRegisrationCar, payload: payload);
if (jsonDecode(res)['status'] == 'success') {
if (res is Map && res['status'] == 'success') {
box.write(BoxName.vin, vin.text);
box.write(BoxName.color, color.text);
box.write(BoxName.model, model.text);
@@ -65,20 +65,19 @@ class CaptainProfileController extends GetxController {
var res = await CRUD().get(
link: AppLink.getCaptainProfile,
payload: {'id': box.read(BoxName.driverID)});
if (res != 'failure') {
var d = jsonDecode(res);
captainProfileData = d['message'];
if (res is Map) {
captainProfileData = res['message'];
update();
box.write(BoxName.sexDriver, d['message']['gender']);
box.write(BoxName.dobDriver, d['message']['birthdate']);
box.write(BoxName.vin, d['message']['vin']);
box.write(BoxName.color, d['message']['color']);
box.write(BoxName.model, d['message']['model']);
box.write(BoxName.carPlate, d['message']['car_plate']);
box.write(BoxName.make, d['message']['make']);
box.write(BoxName.year, d['message']['year']);
box.write(BoxName.expirationDate, d['message']['expiration_date']);
// box.write(BoxName.acc, d['message']['accountBank']);
box.write(BoxName.sexDriver, captainProfileData['gender']);
box.write(BoxName.dobDriver, captainProfileData['birthdate']);
box.write(BoxName.vin, captainProfileData['vin']);
box.write(BoxName.color, captainProfileData['color']);
box.write(BoxName.model, captainProfileData['model']);
box.write(BoxName.carPlate, captainProfileData['car_plate']);
box.write(BoxName.make, captainProfileData['make']);
box.write(BoxName.year, captainProfileData['year']);
box.write(BoxName.expirationDate, captainProfileData['expiration_date']);
// box.write(BoxName.acc, captainProfileData['accountBank']);
update();
}

View File

@@ -3,6 +3,7 @@ import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
import 'package:get/get.dart' hide Response;
import 'package:siro_rider/views/widgets/error_snakbar.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:just_audio/just_audio.dart';
@@ -258,10 +259,7 @@ class VoiceCallController extends GetxController with WidgetsBindingObserver {
final permissionStatus = await Permission.microphone.request();
if (!permissionStatus.isGranted) {
_endCallInternal("permission_denied");
Get.snackbar(
"Error",
"Microphone permission is required for voice calls".tr,
);
mySnackeBarError("Microphone permission is required for voice calls".tr);
return;
}
@@ -276,10 +274,7 @@ class VoiceCallController extends GetxController with WidgetsBindingObserver {
response == 'failure' ||
response['status'] != 'success') {
_endCallInternal("session_creation_failed");
Get.snackbar(
"Error",
"Failed to initiate call session. Please try again.".tr,
);
mySnackeBarError("Microphone permission is required for voice calls".tr);
return;
}
@@ -358,10 +353,7 @@ class VoiceCallController extends GetxController with WidgetsBindingObserver {
final permissionStatus = await Permission.microphone.request();
if (!permissionStatus.isGranted) {
declineCall();
Get.snackbar(
"Error",
"Microphone permission is required for voice calls".tr,
);
mySnackeBarError("Microphone permission is required for voice calls".tr);
return;
}