From 61f17a3febbf11b2cf9ebb1690a51af913d38d9d Mon Sep 17 00:00:00 2001 From: faizatflutter Date: Thu, 16 Apr 2026 12:22:19 +0300 Subject: [PATCH] fixed api localization issue --- assets/langs/ar-SA.json | 10 +- assets/langs/en-US.json | 10 +- lib/core/api/api_client.dart | 95 +++++++++++++++---- .../authentication_view_model.dart | 50 ++++++---- lib/generated/locale_keys.g.dart | 16 +++- lib/services/error_handler_service.dart | 8 +- pubspec.lock | 8 -- 7 files changed, 143 insertions(+), 54 deletions(-) diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 72199078..b8a79321 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -1794,5 +1794,13 @@ "selectSmartWatch": "تعيين", "selectBloodDonationCity": "اختر المدينة", "selectBloodDonationGender": "اختر الجنس", - "selectBloodType": "اختر الفصيلة" + "selectBloodType": "اختر الفصيلة", + "networkErrorTitle": "خطأ في الاتصال", + "networkErrorMessage": "تعذّر الاتصال بالخادم. يرجى التحقق من اتصالك بالإنترنت والمحاولة مجدداً.", + "networkConnectionReset": "انقطع الاتصال. يرجى المحاولة مجدداً.", + "networkTimeout": "انتهت مهلة الطلب. يرجى المحاولة مجدداً.", + "networkUnknownError": "حدث خطأ ما. يرجى المحاولة لاحقاً.", + "networkErrorWhileFetching": "حدث خطأ أثناء تحميل البيانات. يرجى المحاولة مجدداً.", + "networkPleaseCheckInternet": "يرجى التحقق من اتصالك بالإنترنت والمحاولة مجدداً.", + "networkServerErrorNoMessage": "حدث خطأ في الخادم. يرجى المحاولة لاحقاً." } diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 27373b5f..f9d91568 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -1784,7 +1784,15 @@ "doctors2": "Doctor", "illurgyInfomation": "Allergy", "vaccineInfomation": "Vaccine", - "approvals1": "Approvals" + "approvals1": "Approvals", + "networkErrorTitle": "Connection Error", + "networkErrorMessage": "Unable to connect to the server. Please check your internet connection and try again.", + "networkConnectionReset": "The connection was interrupted. Please try again.", + "networkTimeout": "The request timed out. Please try again.", + "networkUnknownError": "Something went wrong. Please try again later.", + "networkErrorWhileFetching": "Something went wrong while loading data. Please try again.", + "networkPleaseCheckInternet": "Please check your internet connection and try again.", + "networkServerErrorNoMessage": "A server error occurred. Please try again later." } diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart index 3c71281c..269b204c 100644 --- a/lib/core/api/api_client.dart +++ b/lib/core/api/api_client.dart @@ -1,12 +1,14 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:developer'; +import 'dart:io'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/api_consts.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/presentation/home/app_update_page.dart'; import 'package:hmg_patient_app_new/routes/app_routes.dart'; import 'package:hmg_patient_app_new/services/analytics/analytics_service.dart'; @@ -172,8 +174,9 @@ class ApiClientImp implements ApiClient { // body['VersionID'] = ApiConsts.appVersionID.toString(); if (!isExternal) { body['VersionID'] = ApiConsts.appVersionID.toString(); - if(!isRCService) - body['Channel'] = ApiConsts.appChannelId.toString(); + if (!isRCService) { + body['Channel'] = ApiConsts.appChannelId.toString(); + } body['IPAdress'] = ApiConsts.appIpAddress; body['generalid'] = ApiConsts.appGeneralId; @@ -224,9 +227,9 @@ class ApiClientImp implements ApiClient { if (!networkStatus) { onFailure( - 'Please Check The Internet Connection 1', + LocaleKeys.networkPleaseCheckInternet.tr(), -1, - failureType: ConnectivityFailure("Please Check The Internet Connection 1"), + failureType: ConnectivityFailure(LocaleKeys.networkPleaseCheckInternet.tr()), ); _analytics.errorTracking.log("internet_connectivity", error: "no internet available"); return; @@ -237,12 +240,37 @@ class ApiClientImp implements ApiClient { debugPrint("uri: ${Uri.parse(url.trim())}"); var requestBodyJSON = json.encode(body); debugPrint("body: $requestBodyJSON", wrapWidth: 2048); - final response = await http.post(Uri.parse(url.trim()), body: requestBody, headers: headers); + + http.Response response; + try { + response = await http.post(Uri.parse(url.trim()), body: requestBody, headers: headers); + } on SocketException catch (e) { + final message = e.message.contains('Connection reset by peer') ? LocaleKeys.networkConnectionReset.tr() : LocaleKeys.networkErrorMessage.tr(); + onFailure(message, -1, failureType: ConnectivityFailure(message)); + _analytics.errorTracking.log(endPoint, error: "SocketException: $e"); + return; + } on http.ClientException catch (e) { + final message = e.message.contains('Connection reset by peer') ? LocaleKeys.networkConnectionReset.tr() : LocaleKeys.networkErrorMessage.tr(); + onFailure(message, -1, failureType: ConnectivityFailure(message)); + _analytics.errorTracking.log(endPoint, error: "ClientException: $e"); + return; + } on TimeoutException catch (_) { + final message = LocaleKeys.networkTimeout.tr(); + onFailure(message, -1, failureType: ConnectivityFailure(message)); + _analytics.errorTracking.log(endPoint, error: "TimeoutException"); + return; + } catch (e) { + final message = LocaleKeys.networkUnknownError.tr(); + onFailure(message, -1, failureType: ConnectivityFailure(message)); + _analytics.errorTracking.log(endPoint, error: "UnknownException: $e"); + return; + } + final int statusCode = response.statusCode; // log("response.body: ${response.body}"); if (statusCode < 200 || statusCode >= 400) { - onFailure('Error While Fetching data', statusCode, failureType: StatusCodeFailure("Error While Fetching data")); - logApiEndpointError(endPoint, 'Error While Fetching data', statusCode); + onFailure(LocaleKeys.networkErrorWhileFetching.tr(), statusCode, failureType: StatusCodeFailure(LocaleKeys.networkErrorWhileFetching.tr())); + logApiEndpointError(endPoint, LocaleKeys.networkErrorWhileFetching.tr(), statusCode); } else { var parsed = json.decode(utf8.decode(response.bodyBytes)); if (isAllowAny) { @@ -277,7 +305,8 @@ class ApiClientImp implements ApiClient { onFailure( parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode, - failureType: UnAuthenticatedUserFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'] ?? "User is not Authenticated", url: url), + failureType: + UnAuthenticatedUserFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'] ?? "User is not Authenticated", url: url), ); // logApiEndpointError(endPoint, "session logged out", statusCode); } @@ -322,16 +351,16 @@ class ApiClientImp implements ApiClient { if (parsed['message'] == null && parsed['ErrorEndUserMessage'] == null) { if (parsed['ErrorSearchMsg'] == null) { onFailure( - "Server Error found with no available message", + LocaleKeys.networkServerErrorNoMessage.tr(), statusCode, - failureType: ServerFailure("Error While Fetching data"), + failureType: ServerFailure(LocaleKeys.networkErrorWhileFetching.tr()), ); - logApiEndpointError(endPoint, "Server Error found with no available message", statusCode); + logApiEndpointError(endPoint, LocaleKeys.networkServerErrorNoMessage.tr(), statusCode); } else { onFailure( parsed['ErrorSearchMsg'], statusCode, - failureType: ServerFailure("Error While Fetching data"), + failureType: ServerFailure(LocaleKeys.networkErrorWhileFetching.tr()), ); logApiEndpointError(endPoint, parsed['ErrorSearchMsg'], statusCode); } @@ -353,7 +382,7 @@ class ApiClientImp implements ApiClient { onFailure( parsed['message'] ?? parsed['message'], statusCode, - failureType: ServerFailure("Error While Fetching data"), + failureType: ServerFailure(LocaleKeys.networkErrorWhileFetching.tr()), ); logApiEndpointError(endPoint, parsed['message'] ?? parsed['message'], statusCode); } else { @@ -414,22 +443,46 @@ class ApiClientImp implements ApiClient { // print("Body : ${json.encode(body)}"); if (await Utils.checkConnection(bypassConnectionCheck: true)) { - final response = await http.get( - Uri.parse(url.trim()), - headers: apiHeaders ?? {'Content-Type': 'application/json', 'Accept': 'application/json'}, - ); + http.Response response; + try { + response = await http.get( + Uri.parse(url.trim()), + headers: apiHeaders ?? {'Content-Type': 'application/json', 'Accept': 'application/json'}, + ); + } on SocketException catch (e) { + final message = e.message.contains('Connection reset by peer') ? LocaleKeys.networkConnectionReset.tr() : LocaleKeys.networkErrorMessage.tr(); + onFailure(message, -1); + _analytics.errorTracking.log(endPoint, error: "SocketException: $e"); + return; + } on http.ClientException catch (e) { + final message = e.message.contains('Connection reset by peer') ? LocaleKeys.networkConnectionReset.tr() : LocaleKeys.networkErrorMessage.tr(); + onFailure(message, -1); + _analytics.errorTracking.log(endPoint, error: "ClientException: $e"); + return; + } on TimeoutException catch (_) { + final message = LocaleKeys.networkTimeout.tr(); + onFailure(message, -1); + _analytics.errorTracking.log(endPoint, error: "TimeoutException"); + return; + } catch (e) { + final message = LocaleKeys.networkUnknownError.tr(); + onFailure(message, -1); + _analytics.errorTracking.log(endPoint, error: "UnknownException: $e"); + return; + } + final int statusCode = response.statusCode; // print("statusCode :$statusCode"); if (statusCode < 200 || statusCode >= 400) { - onFailure('Error While Fetching data', statusCode); - logApiEndpointError(endPoint, 'Error While Fetching data', statusCode); + onFailure(LocaleKeys.networkErrorWhileFetching.tr(), statusCode); + logApiEndpointError(endPoint, LocaleKeys.networkErrorWhileFetching.tr(), statusCode); } else { var parsed = json.decode(utf8.decode(response.bodyBytes)); onSuccess(parsed, statusCode); } } else { - onFailure('Please Check The Internet Connection', -1); + onFailure(LocaleKeys.networkPleaseCheckInternet.tr(), -1); _analytics.errorTracking.log("internet_connectivity", error: "no internet available"); } } diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart index eb922652..4d61e503 100644 --- a/lib/features/authentication/authentication_view_model.dart +++ b/lib/features/authentication/authentication_view_model.dart @@ -15,7 +15,6 @@ import 'package:hmg_patient_app_new/core/common_models/privilege/ProjectDetailLi import 'package:hmg_patient_app_new/core/common_models/privilege/VidaPlusProjectListModel.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/enums.dart'; -import 'package:hmg_patient_app_new/core/utils/loading_utils.dart'; import 'package:hmg_patient_app_new/core/utils/request_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/core/utils/validation_utils.dart'; @@ -369,7 +368,11 @@ class AuthenticationViewModel extends ChangeNotifier { } else if (apiResponse.messageStatus == 1) { if (apiResponse.data['isSMSSent']) { _appState.setAppAuthToken = apiResponse.data['LogInTokenID']; - await sendActivationCode(otpTypeEnum: otpTypeEnum, phoneNumber: phoneNumberController.text, nationalIdOrFileNumber: nationalIdController.text, isForRegister: false); + await sendActivationCode( + otpTypeEnum: otpTypeEnum, + phoneNumber: phoneNumberController.text, + nationalIdOrFileNumber: nationalIdController.text, + isForRegister: false); } else { if (apiResponse.data['IsAuthenticated']) { await checkActivationCode( @@ -431,7 +434,10 @@ class AuthenticationViewModel extends ChangeNotifier { } final resultEither = await _authenticationRepo.sendActivationCodeRepo( - sendActivationCodeReq: request, isRegister: checkIsUserComingForRegister(request: payload), languageID: 'er', isFormFamilyFile: isFormFamilyFile); + sendActivationCodeReq: request, + isRegister: checkIsUserComingForRegister(request: payload), + languageID: 'er', + isFormFamilyFile: isFormFamilyFile); resultEither.fold( (failure) async => await _errorHandlerService.handleError(failure: failure), @@ -508,7 +514,9 @@ class AuthenticationViewModel extends ChangeNotifier { bool isSwitchUser = false, int? patientID, }) async { - bool isForRegister = (_appState.getUserRegistrationPayload.healthId != null || _appState.getUserRegistrationPayload.patientOutSa == true || _appState.getUserRegistrationPayload.patientOutSa == 1); + bool isForRegister = (_appState.getUserRegistrationPayload.healthId != null || + _appState.getUserRegistrationPayload.patientOutSa == true || + _appState.getUserRegistrationPayload.patientOutSa == 1); MyAppointmentsViewModel myAppointmentsVM = getIt(); if (isSwitchUser && _appState.getSuperUserID == null) { @@ -550,7 +558,8 @@ class AuthenticationViewModel extends ChangeNotifier { request["ForRegisteration"] = _appState.getUserRegistrationPayload.isRegister; request["isRegister"] = false; - final resultEither = await _authenticationRepo.checkActivationCodeRepo(newRequest: request, activationCode: activationCode.toString(), isRegister: true); + final resultEither = + await _authenticationRepo.checkActivationCodeRepo(newRequest: request, activationCode: activationCode.toString(), isRegister: true); LoaderBottomSheet.hideLoader(); @@ -861,7 +870,8 @@ class AuthenticationViewModel extends ChangeNotifier { : _appState.getAuthenticatedUser()!.mobileNumber)!; nationalIdController.text = _appState.getAuthenticatedUser()!.patientIdentificationNo!; onSuccess(); - } else if ((loginTypeEnum == LoginTypeEnum.sms || loginTypeEnum == LoginTypeEnum.whatsapp && _appState.getSelectDeviceByImeiRespModelElement == null) && + } else if ((loginTypeEnum == LoginTypeEnum.sms || + loginTypeEnum == LoginTypeEnum.whatsapp && _appState.getSelectDeviceByImeiRespModelElement == null) && _appState.getAuthenticatedUser() != null) { phoneNumberController.text = (_appState.getAuthenticatedUser()!.mobileNumber!.startsWith("0") ? _appState.getAuthenticatedUser()!.mobileNumber!.replaceFirst("0", "") @@ -899,13 +909,17 @@ class AuthenticationViewModel extends ChangeNotifier { } final resultEither = await _authenticationRepo.checkPatientForRegistration(commonAuthanticatedRequest: nRequest); - resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure, onUnHandledFailure: (failur) { - - LoaderBottomSheet.hideLoader(); - _dialogService.showExceptionBottomSheet(message: failur.message, onOkPressed: () { - _navigationService.pop(); - }); - }), (apiResponse) async { + resultEither.fold( + (failure) async => await _errorHandlerService.handleError( + failure: failure, + onUnHandledFailure: (failur) { + LoaderBottomSheet.hideLoader(); + _dialogService.showExceptionBottomSheet( + message: failur.message, + onOkPressed: () { + _navigationService.pop(); + }); + }), (apiResponse) async { checkUserStatusForRegistration(response: apiResponse.data, request: request); }); } @@ -914,7 +928,8 @@ class AuthenticationViewModel extends ChangeNotifier { LoaderBottomSheet.showLoader(); // LoadingUtils.showFullScreenLoader(loadingText: "Setting up your medical file.\nMay take a moment."); - var request = RequestUtils.getUserSignupCompletionRequest(fullName: nameController.text, emailAddress: emailController.text, gender: genderType, maritalStatus: maritalStatus); + var request = RequestUtils.getUserSignupCompletionRequest( + fullName: nameController.text, emailAddress: emailController.text, gender: genderType, maritalStatus: maritalStatus); final resultEither = await _authenticationRepo.registerUser(registrationPayloadDataModelRequest: request); resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async { @@ -1044,7 +1059,8 @@ class AuthenticationViewModel extends ChangeNotifier { biometricEnabled: loginType == 1 || loginType == 2 ? false : true, firstNameN: _appState.getAuthenticatedUser()!.firstNameN, lastNameN: _appState.getAuthenticatedUser()!.lastNameN, - zipCode: _appState.getAuthenticatedUser()!.zipCode //selectedCountrySignup == CountryEnum.others ? '0': selectedCountrySignup.countryCode, + zipCode: + _appState.getAuthenticatedUser()!.zipCode //selectedCountrySignup == CountryEnum.others ? '0': selectedCountrySignup.countryCode, ) .toJson()); resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) async { @@ -1120,7 +1136,9 @@ class AuthenticationViewModel extends ChangeNotifier { _dialogService.showPhoneNumberPickerSheet( // label: "Where would you like to receive OTP?", label: LocaleKeys.receiveOtpToast.tr(), - message: _appState.isArabic() ? "يرجى الاختيار من الخيارات أدناه لاستلام رمز التحقق." "Please select from the below options to receive OTP.", + message: _appState.isArabic() + ? "يرجى الاختيار من الخيارات أدناه لاستلام رمز التحقق." + : "Please select from the below options to receive OTP.", onSMSPress: () { checkUserAuthentication(otpTypeEnum: OTPTypeEnum.sms); }, diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 22cca7e4..1578a0a5 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -1767,6 +1767,10 @@ abstract class LocaleKeys { static const locationServicesDisabled = 'locationServicesDisabled'; static const selectDateTimeKey = 'selectDateTimeKey'; static const medicalKey = 'medicalKey'; + static const doctors2 = 'doctors2'; + static const illurgyInfomation = 'illurgyInfomation'; + static const vaccineInfomation = 'vaccineInfomation'; + static const approvals1 = 'approvals1'; static const convertBloodcholesterolInfo = 'convertBloodcholesterolInfo'; static const carbsAlert = 'carbsAlert'; static const bodyFatAlert = 'bodyFatAlert'; @@ -1783,9 +1787,13 @@ abstract class LocaleKeys { static const selectBloodDonationCity = 'selectBloodDonationCity'; static const selectBloodDonationGender = 'selectBloodDonationGender'; static const selectBloodType = 'selectBloodType'; - static const doctors2 = 'doctors2'; - static const illurgyInfomation = 'illurgyInfomation'; - static const vaccineInfomation = 'vaccineInfomation'; - static const approvals1 = 'approvals1'; + static const networkErrorTitle = 'networkErrorTitle'; + static const networkErrorMessage = 'networkErrorMessage'; + static const networkConnectionReset = 'networkConnectionReset'; + static const networkTimeout = 'networkTimeout'; + static const networkUnknownError = 'networkUnknownError'; + static const networkErrorWhileFetching = 'networkErrorWhileFetching'; + static const networkPleaseCheckInternet = 'networkPleaseCheckInternet'; + static const networkServerErrorNoMessage = 'networkServerErrorNoMessage'; } diff --git a/lib/services/error_handler_service.dart b/lib/services/error_handler_service.dart index bda17275..1e37bb17 100644 --- a/lib/services/error_handler_service.dart +++ b/lib/services/error_handler_service.dart @@ -8,7 +8,8 @@ import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; abstract class ErrorHandlerService { - Future handleError({required Failure failure, Function() onOkPressed, Function(Failure)? onUnHandledFailure, Function(Failure)? onMessageStatusFailure}); + Future handleError( + {required Failure failure, Function() onOkPressed, Function(Failure)? onUnHandledFailure, Function(Failure)? onMessageStatusFailure}); } class ErrorHandlerServiceImp implements ErrorHandlerService { @@ -23,7 +24,8 @@ class ErrorHandlerServiceImp implements ErrorHandlerService { }); @override - Future handleError({required Failure failure, Function()? onOkPressed, Function(Failure)? onUnHandledFailure, Function(Failure)? onMessageStatusFailure}) async { + Future handleError( + {required Failure failure, Function()? onOkPressed, Function(Failure)? onUnHandledFailure, Function(Failure)? onMessageStatusFailure}) async { if (failure is APIException) { loggerService.logError("API Exception: ${failure.message}"); } else if (failure is ServerFailure) { @@ -37,7 +39,7 @@ class ErrorHandlerServiceImp implements ErrorHandlerService { await _showDialog(failure, title: "StatusCodeFailure"); } else if (failure is ConnectivityFailure) { loggerService.logError("ConnectivityFailure : ${failure.message}"); - await _showDialog(failure, title: "ConnectivityFailure ", onOkPressed: () {}); + await _showDialog(failure, title: "ConnectivityFailure "); } else if (failure is UnAuthenticatedUserFailure) { loggerService.logError("URL: ${failure.url} \n UnAuthenticatedUser Failure: ${failure.message}"); await _showDialog(failure, title: "UnAuthenticatedUser Failure", onOkPressed: () => navigationService.replaceAllRoutesAndNavigateToLanding()); diff --git a/pubspec.lock b/pubspec.lock index f8ccd5ee..dd27bab8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -985,14 +985,6 @@ packages: url: "https://pub.dev" source: hosted version: "13.1.4" - hijri_gregorian_calendar: - dependency: "direct main" - description: - name: hijri_gregorian_calendar - sha256: aecdbe3c9365fac55f17b5e1f24086a81999b1e5c9372cb08888bfbe61e07fa1 - url: "https://pub.dev" - source: hosted - version: "0.1.1" html: dependency: transitive description: