diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 0fb36b85..ba1f830e 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -41,6 +41,11 @@ android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" tools:node="remove" /> + + + + + diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index e0faf4e5..37530389 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -1850,5 +1850,6 @@ "points": "نقاط", "transactions": "المعاملات", "pharmacy": "الصيدلية", - "visitsOrders": "الزيارات/الطلبات" + "visitsOrders": "الزيارات/الطلبات", + "earned": "حصل" } diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index e8409260..257b2211 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -1840,7 +1840,8 @@ "points": "Points", "transactions": "Transactions", "pharmacy": "Pharmacy", - "visitsOrders": "Visits/Orders" + "visitsOrders": "Visits/Orders", + "earned": "Earned" } diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart index 8dbc9ce3..bf4ebbed 100644 --- a/lib/core/api_consts.dart +++ b/lib/core/api_consts.dart @@ -4,7 +4,7 @@ import 'package:hmg_patient_app_new/core/enums.dart'; class ApiConsts { static const maxSmallScreen = 660; - static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.preProd; + static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.prod; // static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT diff --git a/lib/core/app_state.dart b/lib/core/app_state.dart index d571fa87..f256321e 100644 --- a/lib/core/app_state.dart +++ b/lib/core/app_state.dart @@ -46,7 +46,11 @@ class AppState { AuthenticatedUser? _authenticatedRootUser; AuthenticatedUser? _authenticatedChildUser; - bool isPaytabsEnabled = true; + bool isPaytabsEnabled = false; + + void setIsPaytabsEnabled(bool value) { + isPaytabsEnabled = value; + } int? _superUserID; bool isChildLoggedIn = false; diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart index eaaa6848..262f7063 100644 --- a/lib/features/authentication/authentication_view_model.dart +++ b/lib/features/authentication/authentication_view_model.dart @@ -1190,6 +1190,7 @@ class AuthenticationViewModel extends ChangeNotifier { _appState.setAuthenticatedUser(activation.list!.first); _appState.setPrivilegeModelList(activation.list!.first.listPrivilege!); _appState.setUserBloodGroup = activation.patientBlodType ?? "N/A"; + _appState.setIsPaytabsEnabled(Utils.havePrivilege(120)); // Refresh privileges after user switching to ensure correct privileges are loaded if (isSwitchUser) { @@ -1719,6 +1720,7 @@ class AuthenticationViewModel extends ChangeNotifier { projectDetailListModel.add(ProjectDetailListModel.fromJson(v)); }); _appState.setProjectsDetailList(projectDetailListModel); + _appState.setIsPaytabsEnabled(Utils.havePrivilege(120)); } }, ); diff --git a/lib/features/paytabs/paytabs_view_model.dart b/lib/features/paytabs/paytabs_view_model.dart index c922c752..f6cfb003 100644 --- a/lib/features/paytabs/paytabs_view_model.dart +++ b/lib/features/paytabs/paytabs_view_model.dart @@ -78,10 +78,15 @@ class PayTabsViewModel extends ChangeNotifier { notifyListeners(); } - startApplePayPayment({Function(PaytabsTransactionResponseModel)? onSuccess, Function(String)? onError}) { - FlutterPaytabsBridge.startApplePayPayment(paymentConfiguration, (event) { + startApplePayPayment({Function(PaytabsTransactionResponseModel)? onSuccess, Function(String)? onError}) async { + bool _callbackFired = false; // prevent duplicate callback invocations + + await FlutterPaytabsBridge.startApplePayPayment(paymentConfiguration, (event) { + if (_callbackFired) return; // ignore any subsequent callback calls + final transactionDetails = event["data"] as Map?; if (event["status"] == "success") { + _callbackFired = true; // Cast Map to Map final data = Map.from(event["data"] as Map); paytabsTransactionResponseModel = PaytabsTransactionResponseModel.fromJson(data); @@ -95,11 +100,13 @@ class PayTabsViewModel extends ChangeNotifier { onError!(errorMessage); } } else if (event["status"] == "error") { + _callbackFired = true; final errorMessage = event["message"] ?? "An error occurred"; debugPrint("Error occurred in transaction: $errorMessage"); debugPrint("Full error event: $event"); onError!(errorMessage); } else if (event["status"] == "event") { + // Intermediate SDK events – do NOT mark _callbackFired, just log final eventMessage = event["message"] ?? "Event occurred"; debugPrint("Event occurred: $eventMessage"); } @@ -107,9 +114,14 @@ class PayTabsViewModel extends ChangeNotifier { } startCardPayment({Function(PaytabsTransactionResponseModel)? onSuccess, Function(String)? onError}) { + bool _callbackFired = false; // prevent duplicate callback invocations + FlutterPaytabsBridge.startCardPayment(paymentConfiguration, (event) { + if (_callbackFired) return; // ignore any subsequent callback calls + final transactionDetails = event["data"] as Map?; if (event["status"] == "success") { + _callbackFired = true; // Cast Map to Map final data = Map.from(event["data"] as Map); paytabsTransactionResponseModel = PaytabsTransactionResponseModel.fromJson(data); @@ -123,11 +135,13 @@ class PayTabsViewModel extends ChangeNotifier { onError!(errorMessage); } } else if (event["status"] == "error") { + _callbackFired = true; final errorMessage = event["message"] ?? "An error occurred"; debugPrint("Error occurred in transaction: $errorMessage"); debugPrint("Full error event: $event"); onError!(errorMessage); } else if (event["status"] == "event") { + // Intermediate SDK events – do NOT mark _callbackFired, just log final eventMessage = event["message"] ?? "Event occurred"; debugPrint("Event occurred: $eventMessage"); } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 34787232..e0dd8614 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -1843,5 +1843,6 @@ abstract class LocaleKeys { static const transactions = 'transactions'; static const pharmacy = 'pharmacy'; static const visitsOrders = 'visitsOrders'; + static const earned = 'earned'; } diff --git a/lib/presentation/home/lakum_wallet_details.dart b/lib/presentation/home/lakum_wallet_details.dart index 79b71ec0..d2ef15f4 100644 --- a/lib/presentation/home/lakum_wallet_details.dart +++ b/lib/presentation/home/lakum_wallet_details.dart @@ -304,7 +304,7 @@ class LakumWalletDetails extends StatelessWidget { Widget _buildTransactionItem(PointsDetails transaction) { // Determine if points were gained or used - bool isGained = transaction.operationType?.toLowerCase() == 'gain' || transaction.operationType?.toLowerCase() == 'credit' || (transaction.points ?? 0) > 0; + bool isGained = transaction.subTransactionType == 1 || transaction.operationType?.toLowerCase() == 'cr' || (transaction.points ?? 0) > 0; Color transactionColor = isGained ? AppColors.habibPharmacyColor : AppColors.primaryRedColor; String pointsText = "${isGained ? '+' : '-'}${transaction.points?.abs() ?? 0}"; @@ -345,7 +345,7 @@ class LakumWalletDetails extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - (transaction.subTransactionTypeDescription ?? transaction.operationType ?? "Transaction").toText14( + (isGained ? LocaleKeys.earned.tr() : LocaleKeys.consumed.tr()).toText14( isBold: true, maxlines: 2, ),