completed till otp receiving

pull/12/head
faizatflutter 2 months ago
parent 3e50a3c89d
commit 84804a59a7

@ -1,7 +1,6 @@
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
@ -9,7 +8,6 @@ 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/services/analytics/analytics_service.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
import 'package:http/http.dart' as http;
@ -19,7 +17,7 @@ abstract class ApiClient {
Future<void> post(
String endPoint, {
required Map<String, dynamic> body,
required Function(dynamic response, int statusCode, {int? messageStatus}) onSuccess,
required Function(dynamic response, int statusCode, {int? messageStatus, String? errorMessage}) onSuccess,
required Function(String error, int statusCode, {int? messageStatus, Failure? failureType}) onFailure,
bool isAllowAny,
bool isExternal,
@ -77,29 +75,26 @@ abstract class ApiClient {
class ApiClientImp implements ApiClient {
final _analytics = getIt<GAnalytics>();
final LoggerService loggerService;
final AppState appState;
final DialogService dialogService;
final LoggerService _loggerService;
final AppState _appState;
ApiClientImp({
required this.loggerService,
required this.dialogService,
required this.appState,
});
required LoggerService loggerService,
required AppState appState,
}) : _appState = appState,
_loggerService = loggerService;
@override
post(
String endPoint, {
required Map<String, dynamic> body,
required Function(dynamic response, int statusCode, {int? messageStatus}) onSuccess,
required Function(dynamic response, int statusCode, {int? messageStatus, String? errorMessage}) onSuccess,
required Function(String error, int statusCode, {int? messageStatus, Failure? failureType}) onFailure,
bool isAllowAny = false,
bool isAllowAny = true,
bool isExternal = false,
bool isRCService = false,
bool bypassConnectionCheck = false,
}) async {
AppState appState = getIt.get<AppState>();
String url;
if (isExternal) {
url = endPoint;
@ -111,39 +106,19 @@ class ApiClientImp implements ApiClient {
}
}
try {
var user = appState.getAuthenticatedUser;
var user = _appState.getAuthenticatedUser;
Map<String, String> headers = {'Content-Type': 'application/json', 'Accept': 'application/json'};
if (!isExternal) {
String? token = appState.appAuthToken;
String? languageID = (appState.postParamsObject?.languageID == 1 ? 'ar' : 'en');
if (endPoint == ApiConsts.sendActivationCode) {
languageID = 'en';
}
String? token = _appState.appAuthToken;
if (body.containsKey('SetupID')) {
body['SetupID'] = body.containsKey('SetupID') ? body['SetupID'] ?? body[''] : SETUP_ID;
} else {}
if (body.containsKey('LanguageID')) {
if (body['LanguageID'] != null) {
body['LanguageID'] = body['LanguageID'] == 'ar'
? 1
: body['LanguageID'] == 'en'
? 2
: body['LanguageID'];
}
}
if (body.containsKey('isDentalAllowedBackend')) {
body['isDentalAllowedBackend'] = body.containsKey('isDentalAllowedBackend') ? body['isDentalAllowedBackend'] ?? IS_DENTAL_ALLOWED_BACKEND : IS_DENTAL_ALLOWED_BACKEND;
}
//Todo: I have converted it to string
body['DeviceTypeID'] = Platform.isIOS
? "1"
: await Utils.isGoogleServicesAvailable()
? "2"
: "3";
if (!body.containsKey('IsPublicRequest')) {
// if (!body.containsKey('PatientType')) {
if (user != null && user.patientType != null) {
@ -158,6 +133,7 @@ class ApiClientImp implements ApiClient {
body['PatientType'] = PATIENT_TYPE_ID.toString();
}
// TODO : These should be from the appState
if (user != null) {
body['TokenID'] = body['TokenID'] ?? token;
body['PatientID'] = body['PatientID'] ?? user.patientID;
@ -175,129 +151,134 @@ class ApiClientImp implements ApiClient {
// request.languageID = (languageID == 'ar' ? 1 : 2);
// request.patientOutSA = (request.zipCode == '966' || request.zipCode == '+966') ? 0 : 1;
// TODO : we will use all these from appState
body['LanguageID'] = body['LanguageID'] ?? "2";
body['VersionID'] = body['VersionID'] ?? "50.0";
body['Channel'] = body['Channel'] ?? "3";
body['IPAdress'] = body['IPAdress'] ?? "10.20.10.20";
body['generalid'] = body['generalid'] ?? "Cs2020@2016\$2958";
body['Latitude'] = body['Latitude'] ?? "0.0";
body['Longitude'] = body['Longitude'] ?? "0.0";
body['DeviceTypeID'] = body['DeviceTypeID'] ??
(Platform.isIOS
? "1"
: await Utils.isGoogleServicesAvailable()
? "2"
: "3");
body['TokenID'] = "@dm!n";
body['VersionID'] = ApiConsts.appVersionID.toString();
body['Channel'] = ApiConsts.appChannelId.toString();
body['IPAdress'] = ApiConsts.appIpAddress;
body['generalid'] = ApiConsts.appGeneralId;
body['LanguageID'] = _appState.getLanguageID().toString();
body['Latitude'] = _appState.userLat.toString();
body['Longitude'] = _appState.userLong.toString();
body['DeviceTypeID'] = _appState.deviceTypeID;
if (_appState.appLoginTokenID.isNotEmpty) {
body['LogInTokenID'] = _appState.appLoginTokenID;
}
body.removeWhere((key, value) => value == null);
log("body: ${json.encode(body)}");
log("uri: ${Uri.parse(url.trim())}");
if (await Utils.checkConnection(bypassConnectionCheck: bypassConnectionCheck)) {
final response = await http.post(Uri.parse(url.trim()), body: json.encode(body), headers: headers);
final bool networkStatus = await Utils.checkConnection(bypassConnectionCheck: bypassConnectionCheck);
if (!networkStatus) {
onFailure(
'Please Check The Internet Connection 1',
-1,
failureType: ConnectivityFailure("Please Check The Internet Connection 1"),
);
_analytics.errorTracking.log("internet_connectivity", error: "no internet available");
return;
}
final int statusCode = response.statusCode;
if (statusCode < 200 || statusCode >= 400) {
onFailure('Error While Fetching data', statusCode, failureType: StatusCodeFailure("Error While Fetching data"));
logApiEndpointError(endPoint, 'Error While Fetching data', statusCode);
final response = await http.post(Uri.parse(url.trim()), body: json.encode(body), headers: headers);
final int statusCode = response.statusCode;
log("response.body: ${response.body}");
if (statusCode < 200 || statusCode >= 400) {
var parsed = json.decode(utf8.decode(response.bodyBytes));
onFailure('Error While Fetching data', statusCode, failureType: StatusCodeFailure("Error While Fetching data"));
logApiEndpointError(endPoint, 'Error While Fetching data', statusCode);
} else {
var parsed = json.decode(utf8.decode(response.bodyBytes));
if (isAllowAny) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']);
} else {
var parsed = json.decode(utf8.decode(response.bodyBytes));
log("parsed: ${jsonEncode(parsed)}");
if (isAllowAny) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']);
if (parsed['Response_Message'] != null) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']);
} else {
if (parsed['Response_Message'] != null) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']);
} else {
if (parsed['ErrorType'] == 4) {
//TODO : handle app update
if (parsed['ErrorType'] == 4) {
//TODO : handle app update
logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
}
if (parsed['ErrorType'] == 2) {
// todo: handle Logout
logApiEndpointError(endPoint, "session logged out", statusCode);
}
if (isAllowAny) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']);
} else if (parsed['IsAuthenticated'] == null) {
if (parsed['isSMSSent'] == true) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']);
} else if (parsed['MessageStatus'] == 1) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']);
} else if (parsed['Result'] == 'OK') {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']);
} else {
onFailure(
parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
statusCode,
failureType: MessageStatusFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']),
);
logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
}
if (parsed['ErrorType'] == 2) {
// todo: handle Logout
logApiEndpointError(endPoint, "session logged out", statusCode);
}
if (isAllowAny) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']);
} else if (parsed['IsAuthenticated'] == null) {
if (parsed['isSMSSent'] == true) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']);
} else if (parsed['MessageStatus'] == 1) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']);
} else if (parsed['Result'] == 'OK') {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']);
} else {
onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode, failureType: ServerFailure("Error While Fetching data"));
logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
}
} else if (parsed['MessageStatus'] == 1 || parsed['SMSLoginRequired'] == true) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']);
} else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) {
if (parsed['SameClinicApptList'] != null) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']);
} else {
if (parsed['message'] == null && parsed['ErrorEndUserMessage'] == null) {
if (parsed['ErrorSearchMsg'] == null) {
onFailure(
"Server Error found with no available message",
statusCode,
failureType: ServerFailure("Error While Fetching data"),
);
logApiEndpointError(endPoint, "Server Error found with no available message", statusCode);
} else {
onFailure(
parsed['ErrorSearchMsg'],
statusCode,
failureType: ServerFailure("Error While Fetching data"),
);
logApiEndpointError(endPoint, parsed['ErrorSearchMsg'], statusCode);
}
} else {
onFailure(
parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
statusCode,
failureType: ServerFailure("Error While Fetching data"),
);
logApiEndpointError(endPoint, parsed['message'] ?? parsed['message'], statusCode);
}
}
} else if (parsed['MessageStatus'] == 1 || parsed['SMSLoginRequired'] == true) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']);
} else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) {
if (parsed['SameClinicApptList'] != null) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']);
} else {
if (parsed['SameClinicApptList'] != null) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']);
} else {
if (parsed['message'] != null) {
if (parsed['message'] == null && parsed['ErrorEndUserMessage'] == null) {
if (parsed['ErrorSearchMsg'] == null) {
onFailure(
parsed['message'] ?? parsed['message'],
"Server Error found with no available message",
statusCode,
failureType: ServerFailure("Error While Fetching data"),
);
logApiEndpointError(endPoint, parsed['message'] ?? parsed['message'], statusCode);
logApiEndpointError(endPoint, "Server Error found with no available message", statusCode);
} else {
onFailure(
parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
parsed['ErrorSearchMsg'],
statusCode,
failureType: ServerFailure("Error While Fetching data"),
);
logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
logApiEndpointError(endPoint, parsed['ErrorSearchMsg'], statusCode);
}
} else {
onFailure(
parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
statusCode,
failureType: UserIntimationFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']),
);
logApiEndpointError(endPoint, parsed['message'] ?? parsed['message'], statusCode);
}
}
} else {
if (parsed['SameClinicApptList'] != null) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']);
} else {
if (parsed['message'] != null) {
onFailure(
parsed['message'] ?? parsed['message'],
statusCode,
failureType: ServerFailure("Error While Fetching data"),
);
logApiEndpointError(endPoint, parsed['message'] ?? parsed['message'], statusCode);
} else {
onFailure(
parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
statusCode,
failureType: ServerFailure("Error While Fetching data"),
);
logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
}
}
}
}
}
} else {
onFailure(
'Please Check The Internet Connection 1',
-1,
failureType: ConnectivityFailure("Please Check The Internet Connection 1"),
);
_analytics.errorTracking.log("internet_connectivity", error: "no internet available");
}
} catch (e) {
loggerService.errorLogs(e.toString());
} catch (e, stackTrace) {
_loggerService.errorLogs(stackTrace.toString());
if (e.toString().contains("ClientException")) {
onFailure('Something went wrong, plase try again', -1, failureType: InvalidCredentials('Something went wrong, plase try again'));
onFailure('ClientException: Something went wrong, Please try again', -1, failureType: InvalidCredentials('ClientException: Something went wrong, plase try again'));
_analytics.errorTracking.log("internet_connectivity", error: "no internet available");
} else {
onFailure(e.toString(), -1);

@ -1,4 +1,4 @@
import 'dart:io';
import 'package:hmg_patient_app_new/core/enums.dart';
var MAX_SMALL_SCREEN = 660;
final OPENTOK_API_KEY = '46209962';
@ -350,7 +350,6 @@ var CAN_PAY_FOR_FOR_WALKIN_APPOINTMENT = 'Services/Doctors.svc/REST/CanPayForWal
var CHANNEL = 3;
var GENERAL_ID = 'Cs2020@2016\$2958';
var IP_ADDRESS = '10.20.10.20';
var VERSION_ID = 18.7;
var SETUP_ID = '91877';
var LANGUAGE = 2;
// var PATIENT_OUT_SA = 0;
@ -702,20 +701,12 @@ var applePayMerchantId = "merchant.com.hmgwebservices";
// var payFortEnvironment = FortEnvironment.test;
// var applePayMerchantId = "merchant.com.hmgwebservices.uat";
// Auth Provider Consts
const String INSERT_DEVICE_IMEI = 'Services/Patients.svc/REST/Patient_INSERTDeviceIMEI';
const String SELECT_DEVICE_IMEI = 'Services/Patients.svc/REST/Patient_SELECTDeviceIMEIbyIMEI';
const String CHECK_PATIENT_AUTH = 'Services/Authentication.svc/REST/CheckPatientAuthentication';
const GET_MOBILE_INFO = 'Services/Authentication.svc/REST/GetMobileLoginInfo';
const SEND_ACTIVATION_CODE = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationType';
const SEND_ACTIVATION_CODE_REGISTER = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationTypeForRegistration';
const CHECK_ACTIVATION_CODE = 'Services/Authentication.svc/REST/CheckActivationCode';
const CHECK_ACTIVATION_CODE_REGISTER = 'Services/Authentication.svc/REST/CheckActivationCodeForRegistration';
const FORGOT_PASSWORD = 'Services/Authentication.svc/REST/CheckActivationCodeForSendFileNo';
const CHECK_PATIENT_FOR_REGISTRATION = "Services/Authentication.svc/REST/CheckPatientForRegisteration";
@ -731,36 +722,49 @@ const SAVE_SETTING = 'Services/Patients.svc/REST/UpdatePateintInfo';
const DEACTIVATE_ACCOUNT = 'Services/Patients.svc/REST/PatientAppleActivation_InsertUpdate';
class ApiConsts {
static const maxSmallScreen = 660;
static bool isDevelopment = true;
static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.uat;
// static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT
static String baseUrl = 'https://hmgwebservices.com/'; // HIS API URL PROD
static String SELECT_DEVICE_IMEI = 'Services/Patients.svc/REST/Patient_SELECTDeviceIMEIbyIMEI';
static num VERSION_ID = 18.9;
static final String selectDeviceImei = 'Services/Patients.svc/REST/Patient_SELECTDeviceIMEIbyIMEI';
static final String sendActivationCode = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationType';
static final String checkPatientAuth = 'Services/Authentication.svc/REST/CheckPatientAuthentication';
static String baseUrl = 'https://hmgwebservices.com/'; // HIS API URL PROD
static setBackendURLs() {
if (isDevelopment) {
baseUrl = "https://uat.hmgwebservices.com/";
} else {
baseUrl = "https://hmgwebservices.com/";
switch (appEnvironmentType) {
case AppEnvironmentTypeEnum.prod:
baseUrl = "https://hmgwebservices.com/";
break;
case AppEnvironmentTypeEnum.dev:
baseUrl = "https://uat.hmgwebservices.com/";
break;
case AppEnvironmentTypeEnum.uat:
baseUrl = "https://uat.hmgwebservices.com/";
break;
case AppEnvironmentTypeEnum.preProd:
baseUrl = "https://uat.hmgwebservices.com/";
break;
case AppEnvironmentTypeEnum.qa:
baseUrl = "https://uat.hmgwebservices.com/";
break;
case AppEnvironmentTypeEnum.staging:
baseUrl = "https://uat.hmgwebservices.com/";
break;
}
}
static final String selectDeviceImei = 'Services/Patients.svc/REST/Patient_SELECTDeviceIMEIbyIMEI';
static final String checkPatientAuth = 'Services/Authentication.svc/REST/CheckPatientAuthentication';
static final Map<String, String> packagesAuthHeader = {};
}
static final String sendActivationCode = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationType';
static final String sendActivationCodeRegister = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationTypeForRegistration';
static final String checkActivationCode = 'Services/Authentication.svc/REST/CheckActivationCode';
static final String checkActivationCodeRegister = 'Services/Authentication.svc/REST/CheckActivationCodeForRegistration';
// static values for Api
static final double appVersionID = 18.7;
static final int appChannelId = 3;
static final String appIpAddress = "10.20.10.20";
static final String appGeneralId = "Cs2020@2016\$2958";
}

@ -1,70 +1,24 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:hmg_patient_app_new/core/post_params_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'api_consts.dart' as ApiConsts;
class AppState {
NavigationService navigationService;
AppState({
required this.navigationService,
});
bool isAuthenticated = false;
set setIsAuthenticated(v) => isAuthenticated = v;
String deviceToken = "";
set setDeviceToken(v) => deviceToken = v;
AppState({required this.navigationService});
String appAuthToken = "";
set setAppAuthToken(v) => appAuthToken = v;
double userLat = 0.0;
set setUserLat(v) => userLat = v;
set setUserLong(v) => userLong = v;
// TODO: GETTER SETTER FOR SESSION ID
String sessionId = "";
set setSessionId(v) => sessionId = v;
final PostParamsModel _postParamsInitConfig = PostParamsModel(
channel: 3,
versionID: ApiConsts.VERSION_ID,
ipAddress: '10.20.10.20',
generalId: 'Cs2020@2016\$2958',
deviceTypeID: "2",
sessionID: 'TMRhVmkGhOsvamErw',
);
void setPostParamsInitConfig() {
isAuthenticated = false;
_postParams = _postParamsInitConfig;
}
PostParamsModel? _postParams;
PostParamsModel? get postParamsObject => _postParams;
Map<String, dynamic> get postParamsJson => isAuthenticated ? (_postParams?.toJsonAfterLogin() ?? {}) : (_postParams?.toJson() ?? {});
void setPostParamsModel(PostParamsModel _postParams) {
this._postParams = _postParams;
}
double userLat = 0.0;
double userLong = 0.0;
set setUserLong(v) => userLong = v;
bool isArabic() => EasyLocalization.of(navigationService.navigatorKey.currentContext!)?.locale.languageCode == "ar";
int getLanguageID(context) => EasyLocalization.of(context)?.locale.languageCode == "ar" ? 1 : 2;
int getLanguageID() => EasyLocalization.of(navigationService.navigatorKey.currentContext!)?.locale.languageCode == "ar" ? 1 : 2;
AuthenticatedUser? _authenticatedUser;
@ -82,7 +36,27 @@ class AppState {
SelectDeviceByImeiRespModelElement? get getSelectDeviceByImeiRespModelElement => _selectDeviceByImeiRespModelElement;
String appLoginToken = "";
String appLoginTokenID = "";
set setAppLoginTokenID(v) => appLoginTokenID = v;
String deviceToken = "";
set setDeviceToken(v) => deviceToken = v;
String appAuthToken = "";
set setAppAuthToken(v) => appAuthToken = v;
String sessionId = "";
set setSessionId(v) => sessionId = v;
bool isAuthenticated = false;
set setIsAuthenticated(v) => isAuthenticated = v;
String deviceTypeID = "";
set setAppLoginToken(v) => appLoginToken = v;
set setDeviceTypeID(v) => deviceTypeID = v;
}

@ -32,7 +32,7 @@ class AppDependencies {
printer: PrettyPrinter(
methodCount: 2,
errorMethodCount: 5,
lineLength: 100,
lineLength: 1000,
colors: true,
printEmojis: true,
),
@ -63,7 +63,7 @@ class AppDependencies {
final sharedPreferences = await SharedPreferences.getInstance();
getIt.registerLazySingleton<CacheService>(() => CacheServiceImp(sharedPreferences: sharedPreferences, loggerService: getIt()));
getIt.registerLazySingleton<ApiClient>(() => ApiClientImp(loggerService: getIt(), dialogService: getIt(), appState: getIt()));
getIt.registerLazySingleton<ApiClient>(() => ApiClientImp(loggerService: getIt(), appState: getIt()));
// Repositories
getIt.registerLazySingleton<CommonRepo>(() => CommonRepoImp(loggerService: getIt()));

@ -22,13 +22,6 @@ enum ViewStateEnum {
errorLocal,
}
enum LoginTypeEnum {
fromLogin,
silentLogin,
silentWithOTP,
}
enum CountryEnum { saudiArabia, unitedArabEmirates }
enum SelectionTypeEnum { dropdown, calendar }
@ -43,6 +36,8 @@ enum OTPTypeEnum { sms, whatsapp }
enum LoginTypeEnum { sms, whatsapp, face, fingerprint }
enum AppEnvironmentTypeEnum { dev, uat, preProd, qa, staging, prod }
extension LoginTypeExtension on LoginTypeEnum {
int get toInt {
switch (this) {

@ -13,6 +13,20 @@ class ServerFailure extends Failure {
List<Object?> get props => [message];
}
class UserIntimationFailure extends Failure {
const UserIntimationFailure(super.message);
@override
List<Object?> get props => [message];
}
class MessageStatusFailure extends Failure {
const MessageStatusFailure(super.message);
@override
List<Object?> get props => [message];
}
class StatusCodeFailure extends Failure {
const StatusCodeFailure(super.message);
@ -48,7 +62,6 @@ class UnknownFailure extends Failure {
List<Object?> get props => [message];
}
class DuplicateUsername extends Failure {
const DuplicateUsername(String? message) : super(message ?? '');
@ -62,5 +75,3 @@ class InvalidCredentials extends Failure {
@override
List<Object?> get props => [message];
}

@ -14,7 +14,19 @@ class PostParamsModel {
String? sessionID;
String? setupID;
PostParamsModel({this.versionID, this.channel, this.languageID, this.logInTokenID, this.tokenID, this.language, this.ipAddress, this.generalId, this.latitude, this.longitude, this.deviceTypeID, this.sessionID});
PostParamsModel(
{this.versionID,
this.channel,
this.languageID,
this.logInTokenID,
this.tokenID,
this.language,
this.ipAddress,
this.generalId,
this.latitude,
this.longitude,
this.deviceTypeID,
this.sessionID});
PostParamsModel.fromJson(Map<String, dynamic> json) {
versionID = json['VersionID'];

@ -13,11 +13,11 @@ class LoadingUtils {
static bool get isLoading => _isLoadingVisible;
static showFullScreenLoading({bool barrierDismissible = true}) {
static showFullScreenLoader({bool barrierDismissible = true}) {
if (!_isLoadingVisible) {
_isLoadingVisible = true;
final context = _navigationService.navigatorKey.currentContext;
log("context:$context");
log("got the context in showFullScreenLoading");
if (context == null) return;
showDialog(

@ -1,9 +1,48 @@
import 'dart:developer';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/features/authentication/models/request_models/send_activation_request_model.dart';
class RequestUtils {
static dynamic getPatientAuthenticationRequest({
required String phoneNumber,
required String nationId,
required OTPTypeEnum otpTypeEnum,
required bool patientOutSA,
required bool isForRegister,
required int? patientId,
required String zipCode,
}) {
bool fileNo = false;
if (nationId.isNotEmpty) {
fileNo = nationId.length < 10;
}
var request = SendActivationRequest();
if (phoneNumber.isNotEmpty) {
request.patientMobileNumber = int.parse(phoneNumber);
}
request.oTPSendType = otpTypeEnum.toInt(); // could map OTPTypeEnum if needed
request.zipCode = zipCode; // or countryCode if defined elsewhere
if (isForRegister) {
// request.searchType = registeredData.searchType ?? 1;
// request.patientID = registeredData.patientID ?? 0;
// request.patientIdentificationID = request.nationalID = registeredData.patientIdentificationID ?? '0';
// request.dob = registeredData.dob;
// request.isRegister = registeredData.isRegister;
} else {
if (fileNo) {
request.patientID = patientId ?? int.parse(nationId);
request.patientIdentificationID = request.nationalID = "";
request.searchType = 2;
} else {
request.patientID = 0;
request.searchType = 1;
request.patientIdentificationID = request.nationalID = nationId.isNotEmpty ? nationId : '0';
}
request.isRegister = false;
}
return request;
}
static dynamic getCommonRequestWelcome({
required String phoneNumber,
required OTPTypeEnum otpTypeEnum,
@ -19,7 +58,6 @@ class RequestUtils {
if (nationIdText.isNotEmpty) {
fileNo = nationIdText.length < 10;
}
log("phoneNumber: ${phoneNumber}");
var request = SendActivationRequest();
request.patientMobileNumber = int.parse(phoneNumber);
request.mobileNo = '0$phoneNumber';
@ -53,39 +91,38 @@ class RequestUtils {
return request;
}
static getCommonRequestAuthProvider({
static getCommonRequestSendActivationCode({
required OTPTypeEnum otpTypeEnum,
required registeredData,
required deviceToken,
required mobileNumber,
required zipCode,
required patientOutSA,
required loginTokenID,
required selectedOption,
required String mobileNumber,
required String zipCode,
required int? patientId,
required String? nationalId,
required bool patientOutSA,
required int selectedLoginType,
required bool isForRegister,
required bool isFileNo,
}) {
var request = SendActivationRequest();
request.patientMobileNumber = mobileNumber;
if (mobileNumber.isNotEmpty) {
request.patientMobileNumber = int.parse(mobileNumber);
}
request.mobileNo = '0$mobileNumber';
request.deviceToken = deviceToken;
request.projectOutSA = patientOutSA == true ? true : false;
request.loginType = selectedOption;
request.projectOutSA = patientOutSA;
request.loginType = selectedLoginType;
request.oTPSendType = otpTypeEnum.toInt(); //this.selectedOption == 1 ? 1 : 2;
request.zipCode = zipCode;
request.logInTokenID = loginTokenID ?? "";
if (registeredData != null) {
request.searchType = registeredData.searchType ?? 1;
request.patientID = registeredData.patientID ?? 0;
request.patientIdentificationID = request.nationalID = registeredData.patientIdentificationID ?? '0';
request.dob = registeredData.dob;
request.isRegister = registeredData.isRegister;
if (isForRegister) {
// request.searchType = registeredData.searchType ?? 1;
// request.patientID = registeredData.patientID ?? 0;
// request.patientIdentificationID = request.nationalID = registeredData.patientIdentificationID ?? '0';
// request.dob = registeredData.dob;
// request.isRegister = registeredData.isRegister;
} else {
request.searchType = request.searchType ?? 2;
request.searchType = isFileNo ? 2 : 1;
request.patientID = patientId ?? 0;
request.nationalID = request.nationalID ?? '0';
request.patientIdentificationID = request.patientIdentificationID ?? '0';
request.nationalID = nationalId ?? '0';
request.patientIdentificationID = nationalId ?? '0';
request.isRegister = false;
}
request.deviceTypeID = request.searchType;

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
@ -5,13 +7,15 @@ class ValidationUtils {
static final DialogService _dialogService = getIt.get<DialogService>();
static bool isValidatePhoneAndId({String? nationalId, String? phoneNumber}) {
log("phoneNumber: $phoneNumber");
log("nationalId: $nationalId");
if (nationalId == null || nationalId.isEmpty) {
_dialogService.showErrorDialog(message: "Please enter a valid national ID or file number", onOkPressed: () {});
_dialogService.showErrorBottomSheet(message: "Please enter a valid national ID or file number", onOkPressed: () {});
return false;
}
if (phoneNumber == null || phoneNumber.isEmpty) {
_dialogService.showErrorDialog(message: "Please enter a valid phone number", onOkPressed: () {});
_dialogService.showErrorBottomSheet(message: "Please enter a valid phone number", onOkPressed: () {});
return false;
}
return true;

@ -1,12 +1,10 @@
import 'dart:async';
import 'dart:io';
import 'package:dartz/dartz.dart';
import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_activation_code_resp_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
@ -18,7 +16,7 @@ abstract class AuthenticationRepo {
Future<Either<Failure, GenericApiModel<dynamic>>> checkPatientAuthentication({required dynamic checkPatientAuthenticationReq});
Future<Either<Failure, GenericApiModel<dynamic>>> sendActivationCodeRepo({
required dynamic checkPatientAuthenticationReq,
required dynamic sendActivationCodeReq,
String? languageID,
bool isRegister = false,
});
@ -48,7 +46,7 @@ class AuthenticationRepoImp implements AuthenticationRepo {
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus}) {
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = response['Patient_SELECTDeviceIMEIbyIMEIList'];
if (list == null || list.isEmpty) {
@ -59,7 +57,7 @@ class AuthenticationRepoImp implements AuthenticationRepo {
apiResponse = GenericApiModel<SelectDeviceByImeiRespModelElement>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
errorMessage: errorMessage,
data: model,
);
} catch (e) {
@ -81,13 +79,6 @@ class AuthenticationRepoImp implements AuthenticationRepo {
String? languageID,
}) async {
int isOutKsa = (checkPatientAuthenticationReq.zipCode == '966' || checkPatientAuthenticationReq.zipCode == '+966') ? 0 : 1;
//TODO : We will use all these from AppState directly in the ApiClient
checkPatientAuthenticationReq.versionID = VERSION_ID;
checkPatientAuthenticationReq.channel = CHANNEL;
checkPatientAuthenticationReq.iPAdress = IP_ADDRESS;
checkPatientAuthenticationReq.generalid = GENERAL_ID;
checkPatientAuthenticationReq.languageID = (languageID == 'ar' ? 1 : 2);
checkPatientAuthenticationReq.patientOutSA = isOutKsa;
try {
GenericApiModel<dynamic>? apiResponse;
@ -98,12 +89,12 @@ class AuthenticationRepoImp implements AuthenticationRepo {
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus}) {
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
errorMessage: errorMessage,
data: response,
);
} catch (e) {
@ -121,41 +112,31 @@ class AuthenticationRepoImp implements AuthenticationRepo {
@override
Future<Either<Failure, GenericApiModel<dynamic>>> sendActivationCodeRepo({
required dynamic checkPatientAuthenticationReq,
required dynamic sendActivationCodeReq,
String? languageID,
bool isRegister = false,
}) async {
int isOutKsa = (checkPatientAuthenticationReq.zipCode == '966' || checkPatientAuthenticationReq.zipCode == '+966') ? 0 : 1;
//TODO : We will use all these from AppState directly in the ApiClient
checkPatientAuthenticationReq.versionID = VERSION_ID;
checkPatientAuthenticationReq.channel = CHANNEL;
checkPatientAuthenticationReq.iPAdress = IP_ADDRESS;
checkPatientAuthenticationReq.generalid = GENERAL_ID;
checkPatientAuthenticationReq.languageID = isRegister ? (languageID == 'ar' ? 1 : 2) : 2;
checkPatientAuthenticationReq.deviceTypeID = Platform.isIOS ? 1 : 2;
checkPatientAuthenticationReq.patientOutSA = isOutKsa;
checkPatientAuthenticationReq.isDentalAllowedBackend = false;
// Pick correct endpoint
int isOutKsa = (sendActivationCodeReq.zipCode == '966' || sendActivationCodeReq.zipCode == '+966') ? 0 : 1;
sendActivationCodeReq.patientOutSA = isOutKsa;
sendActivationCodeReq.isDentalAllowedBackend = false;
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
isRegister ? SEND_ACTIVATION_CODE_REGISTER : SEND_ACTIVATION_CODE,
body: checkPatientAuthenticationReq.toJson(),
isRegister ? ApiConsts.sendActivationCodeRegister : ApiConsts.sendActivationCode,
body: sendActivationCodeReq.toJson(),
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus}) {
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: CheckActivationCode.fromJson(response),
errorMessage: errorMessage,
data: response,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
@ -179,18 +160,12 @@ class AuthenticationRepoImp implements AuthenticationRepo {
}) async {
newRequest.activationCode = activationCode ?? "0000";
newRequest.isSilentLogin = activationCode != null ? false : true;
newRequest.versionID = VERSION_ID;
newRequest.channel = CHANNEL;
newRequest.iPAdress = IP_ADDRESS;
newRequest.generalid = GENERAL_ID;
newRequest.deviceTypeID = Platform.isIOS ? 1 : 2;
newRequest.projectOutSA = newRequest.zipCode == '966' ? false : true;
newRequest.isDentalAllowedBackend = false;
newRequest.forRegisteration = newRequest.isRegister ?? false;
newRequest.isRegister = false;
final endpoint = isRegister ? CHECK_ACTIVATION_CODE_REGISTER : CHECK_ACTIVATION_CODE;
final endpoint = isRegister ? ApiConsts.checkActivationCodeRegister : ApiConsts.checkActivationCode;
try {
GenericApiModel<dynamic>? apiResponse;
@ -202,12 +177,12 @@ class AuthenticationRepoImp implements AuthenticationRepo {
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus}) {
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
errorMessage: errorMessage,
data: response,
);
} catch (e) {

@ -61,7 +61,7 @@ class AuthenticationViewModel extends ChangeNotifier {
Future<void> onLoginPressed() async {
try {
LoadingUtils.showFullScreenLoading();
LoadingUtils.showFullScreenLoader();
//TODO: We will remove this delay
await Future.delayed(Duration(seconds: 3));
var data = _appState.getSelectDeviceByImeiRespModelElement;
@ -74,7 +74,7 @@ class AuthenticationViewModel extends ChangeNotifier {
} catch (e) {
log("Error in onLoginPressed: $e");
LoadingUtils.hideFullScreenLoader();
_dialogService.showErrorDialog(message: "An unexpected error occurred. Please try again.", onOkPressed: () {});
_dialogService.showErrorBottomSheet(message: "An unexpected error occurred. Please try again.", onOkPressed: () {});
}
}
@ -97,7 +97,7 @@ class AuthenticationViewModel extends ChangeNotifier {
if (apiResponse.messageStatus == 1) {
onSuccess(apiResponse.data);
} else if (apiResponse.messageStatus == 2) {
_dialogService.showErrorDialog(message: "Message Status = 2", onOkPressed: () {});
_dialogService.showErrorBottomSheet(message: "Message Status = 2", onOkPressed: () {});
}
},
);
@ -144,70 +144,84 @@ class AuthenticationViewModel extends ChangeNotifier {
}
}, onError: (String error) {
LoadingUtils.hideFullScreenLoader();
_dialogService.showErrorDialog(message: error, onOkPressed: () {});
_dialogService.showErrorBottomSheet(message: error, onOkPressed: () {});
});
}
Future<void> checkUserAuthentication({required OTPTypeEnum otpTypeEnum, Function(dynamic)? onSuccess, Function(String)? onError}) async {
// TODO: THIS SHOULD BE REMOVED LATER ON AND PASSED FROM APP STATE DIRECTLY INTO API CLIENT. BECAUSE THIS API ONLY NEEDS FEW PARAMS FROM USER
if (phoneNumberController.text.isEmpty) {
phoneNumberController.text = "504278212";
}
bool isValidated = ValidationUtils.isValidatePhoneAndId(
phoneNumber: phoneNumberController.text,
nationalId: nationalIdController.text,
);
if (!isValidated) return;
dynamic checkPatientAuthenticationReq = RequestUtils.getCommonRequestWelcome(
if (!isValidated) {
return;
}
LoadingUtils.showFullScreenLoader();
dynamic checkPatientAuthenticationReq = RequestUtils.getPatientAuthenticationRequest(
phoneNumber: phoneNumberController.text,
nationIdText: nationalIdController.text,
nationId: nationalIdController.text,
isForRegister: false,
patientOutSA: false,
otpTypeEnum: otpTypeEnum,
deviceToken: 'dummyDeviceToken123',
patientOutSA: true,
loginTokenID: 'dummyLoginToken456',
registeredData: null,
patientId: 12345,
countryCode: 'SA',
patientId: 0,
zipCode: '966',
);
final result = await _authenticationRepo.checkPatientAuthentication(checkPatientAuthenticationReq: checkPatientAuthenticationReq);
LoadingUtils.hideFullScreenLoader();
result.fold(
(failure) async => await _errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.data['isSMSSent']) {
// TODO: set this in AppState
_appState.setAppLoginToken = apiResponse.data['LogInTokenID'];
// sharedPref.setString(LOGIN_TOKEN_ID, value['LogInTokenID']);
// loginTokenID = value['LogInTokenID'],
// sharedPref.setObject(REGISTER_DATA_FOR_LOGIIN, request),
sendActivationCode(otpTypeEnum: otpTypeEnum);
} else {
if (apiResponse.data['IsAuthenticated']) {
checkActivationCode(
onWrongActivationCode: (String? message) {},
activationCode: 0000,
(apiResponse) async {
if (apiResponse.messageStatus == 2) {
await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty", onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
if (apiResponse.data['isSMSSent']) {
_appState.setAppLoginTokenID = apiResponse.data['LogInTokenID'];
sendActivationCode(
otpTypeEnum: otpTypeEnum,
phoneNumber: phoneNumberController.text,
nationalIdOrFileNumber: nationalIdController.text,
);
} else {
if (apiResponse.data['IsAuthenticated']) {
await checkActivationCode(
onWrongActivationCode: (String? message) {},
activationCode: 0000,
);
}
}
}
},
);
}
Future<void> sendActivationCode({required OTPTypeEnum otpTypeEnum}) async {
var request = RequestUtils.getCommonRequestAuthProvider(
Future<void> sendActivationCode({
required OTPTypeEnum otpTypeEnum,
required String nationalIdOrFileNumber,
required String phoneNumber,
}) async {
var request = RequestUtils.getCommonRequestSendActivationCode(
otpTypeEnum: otpTypeEnum,
registeredData: null,
deviceToken: "dummyLoginToken456",
mobileNumber: "0567184134",
zipCode: "SA",
patientOutSA: true,
loginTokenID: "dummyLoginToken456",
selectedOption: otpTypeEnum.toInt(),
patientId: 12345,
mobileNumber: phoneNumber,
selectedLoginType: otpTypeEnum.toInt(),
zipCode: "966",
nationalId: nationalIdOrFileNumber,
isFileNo: false,
patientId: 0,
isForRegister: false,
patientOutSA: false,
);
// TODO: GET APP SMS SIGNATURE HERE
request.sMSSignature = "";
request.sMSSignature = "enKTDcqbOVd";
// GifLoaderDialogUtils.showMyDialog(context);
bool isForRegister = healthId != null || isDubai;
@ -218,22 +232,28 @@ class AuthenticationViewModel extends ChangeNotifier {
request.healthId = healthId;
request.isHijri = isHijri;
} else {
request.dob = "";
request.healthId = "";
request.isHijri = 0;
// request.dob = "";
// request.healthId = "";
// request.isHijri = 0;
}
final resultEither = await _authenticationRepo.sendActivationCodeRepo(
checkPatientAuthenticationReq: request,
sendActivationCodeReq: request,
isRegister: isForRegister,
languageID: 'er',
);
resultEither.fold(
(failure) async => await _errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.data != null && apiResponse.data['isSMSSent'] == true) {
// startSMSService(otpTypeEnum.toInt());
navigateToOTPScreen(otpTypeEnum: otpTypeEnum, phoneNumber: request.mobileNumber);
(apiResponse) async {
if (apiResponse.messageStatus == 2) {
await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty");
} else {
if (apiResponse.data != null && apiResponse.data['isSMSSent'] == true) {
navigateToOTPScreen(otpTypeEnum: otpTypeEnum, phoneNumber: phoneNumber);
} else {
navigateToOTPScreen(otpTypeEnum: otpTypeEnum, phoneNumber: phoneNumber);
}
}
},
);
@ -254,7 +274,6 @@ class AuthenticationViewModel extends ChangeNotifier {
nationIdText: '1234567890',
countryCode: 'SA',
).toJson();
dynamic res;
bool isForRegister = healthId != null || isDubai;
if (isForRegister) {
@ -267,7 +286,6 @@ class AuthenticationViewModel extends ChangeNotifier {
activationCode: activationCode.toString(),
isRegister: true,
);
res = resultEither;
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) {
final activation = CheckActivationCode.fromJson(apiResponse.data as Map<String, dynamic>);
@ -283,7 +301,6 @@ class AuthenticationViewModel extends ChangeNotifier {
activationCode: activationCode.toString(),
isRegister: false,
);
res = resultEither;
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) {
final activation = CheckActivationCode.fromJson(resultEither as Map<String, dynamic>);

@ -29,38 +29,38 @@ class SendActivationRequest {
int? status;
int? familyRegionID;
bool? isPatientExcluded;
SendActivationRequest(
{this.patientMobileNumber,
this.mobileNo,
this.deviceToken,
this.projectOutSA,
this.loginType,
this.zipCode,
this.isRegister,
this.logInTokenID,
this.searchType,
this.patientID,
this.nationalID,
this.patientIdentificationID,
this.oTPSendType,
this.languageID,
this.versionID,
this.channel,
this.iPAdress,
this.generalid,
this.patientOutSA,
this.sessionID,
this.isDentalAllowedBackend,
this.deviceTypeID,
this.sMSSignature,
this.dob,
this.isHijri,
this.healthId,
this.responseID,
this.status,
this.familyRegionID,
this.isPatientExcluded
});
this.mobileNo,
this.deviceToken,
this.projectOutSA,
this.loginType,
this.zipCode,
this.isRegister,
this.logInTokenID,
this.searchType,
this.patientID,
this.nationalID,
this.patientIdentificationID,
this.oTPSendType,
this.languageID,
this.versionID,
this.channel,
this.iPAdress,
this.generalid,
this.patientOutSA,
this.sessionID,
this.isDentalAllowedBackend,
this.deviceTypeID,
this.sMSSignature,
this.dob,
this.isHijri,
this.healthId,
this.responseID,
this.status,
this.familyRegionID,
this.isPatientExcluded});
SendActivationRequest.fromJson(Map<String, dynamic> json) {
patientMobileNumber = json['PatientMobileNumber'];

@ -45,7 +45,7 @@ class LabRepoImp implements LabRepo {
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus}) {
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = response['ListPLO'];
if (list == null || list.isEmpty) {

@ -48,7 +48,7 @@ class PrescriptionsRepoImp implements PrescriptionsRepo {
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus}) {
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = response['PatientPrescriptionList'];
if (list == null || list.isEmpty) {
@ -111,7 +111,7 @@ class PrescriptionsRepoImp implements PrescriptionsRepo {
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus}) {
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = prescriptionsResponseModel.isInOutPatient! ? response['ListPRM'] : response['INP_GetPrescriptionReport_List'];
if (list == null || list.isEmpty) {

@ -1,8 +1,8 @@
import 'package:dartz/dartz.dart';
import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:dartz/dartz.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/features/radiology/models/resp_models/patient_radiology_response_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
@ -45,7 +45,7 @@ class RadiologyRepoImp implements RadiologyRepo {
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus}) {
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
final radOrders;
try {
if (response['FinalRadiologyList'] != null && response['FinalRadiologyList'].length != 0) {

@ -5,7 +5,9 @@ import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.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/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
@ -33,6 +35,16 @@ class MyHttpOverrides extends HttpOverrides {
}
}
Future<void> callAppStateInitializations() async {
final String deviceTypeId = (Platform.isIOS
? "1"
: await Utils.isGoogleServicesAvailable()
? "2"
: "3");
AppState appState = getIt.get<AppState>();
appState.setDeviceTypeID = deviceTypeId;
}
Future<void> callInitializations() async {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();
@ -40,6 +52,7 @@ Future<void> callInitializations() async {
AppDependencies.addDependencies();
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
HttpOverrides.global = MyHttpOverrides();
await callAppStateInitializations();
}
void main() async {

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
@ -86,7 +88,7 @@ class _LoginScreen extends State<LoginScreen> {
icon: AppAssets.login1,
iconColor: Colors.white,
onPressed: () {
showLoginModelSheet(context: context, textController: authVm.phoneNumberController, authViewModel: authVm);
showLoginModelSheet(context: context, phoneNumberController: authVm.phoneNumberController, authViewModel: authVm);
// if (nationIdController.text.isNotEmpty) {
// } else {
@ -145,7 +147,7 @@ class _LoginScreen extends State<LoginScreen> {
void showLoginModelSheet({
required BuildContext context,
required TextEditingController? textController,
required TextEditingController? phoneNumberController,
required AuthenticationViewModel authViewModel,
}) {
context.showBottomSheet(
@ -160,7 +162,7 @@ class _LoginScreen extends State<LoginScreen> {
child: GenericBottomSheet(
countryCode: "966",
initialPhoneNumber: "",
textController: textController,
textController: phoneNumberController,
isEnableCountryDropdown: true,
onCountryChange: (value) {},
onChange: (String? value) {},
@ -193,6 +195,8 @@ class _LoginScreen extends State<LoginScreen> {
child: CustomButton(
text: LocaleKeys.sendOTPWHATSAPP.tr(),
onPressed: () async {
log("phoneNumberController: ${phoneNumberController == null}");
log("phoneNumberControllerVa: ${phoneNumberController?.text}");
await authViewModel.checkUserAuthentication(otpTypeEnum: OTPTypeEnum.whatsapp);
},
backgroundColor: Colors.white,

@ -206,6 +206,7 @@ class _RegisterNew extends State<RegisterNew> {
child: GenericBottomSheet(
countryCode: "966",
initialPhoneNumber: "",
isEnableCountryDropdown: true,
textController: TextEditingController(),
onChange: (String? value) {},
buttons: [

@ -16,10 +16,8 @@ import 'package:hmg_patient_app_new/presentation/home/widgets/habib_wallet_card.
import 'package:hmg_patient_app_new/presentation/home/widgets/large_service_card.dart';
import 'package:hmg_patient_app_new/presentation/home/widgets/small_service_card.dart';
import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart';
import 'package:hmg_patient_app_new/providers/bottom_navigation_provider.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/bottom_navigation/bottom_navigation.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
import 'package:provider/provider.dart';
@ -37,246 +35,244 @@ class _LandingPageState extends State<LandingPage> {
AppState appState = getIt.get<AppState>();
NavigationService navigationService = getIt.get<NavigationService>();
final AuthenticationViewModel authenticationViewModel = context.read<AuthenticationViewModel>();
return Consumer<BottomNavigationProvider>(builder: (context, navigationProvider, child) {
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: Padding(
padding: EdgeInsets.all(24.h),
child: SingleChildScrollView(
child: Column(
children: [
Padding(
padding: EdgeInsets.only(top: 50.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CustomButton(
text: LocaleKeys.loginOrRegister.tr(context: context),
onPressed: () async {
await authenticationViewModel.onLoginPressed();
},
backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA),
textColor: Color(0xffED1C2B),
fontSize: 16,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 50,
),
Utils.buildSvgWithAssets(
icon: AppAssets.contact_icon,
width: 24,
height: 24,
).onPress(() {
Navigator.of(context).push(
FadePage(
page: MedicalFilePage(),
// page: LoginScreen(),
),
);
}),
],
),
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: Padding(
padding: EdgeInsets.all(24.h),
child: SingleChildScrollView(
child: Column(
children: [
Padding(
padding: EdgeInsets.only(top: 50.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CustomButton(
text: LocaleKeys.loginOrRegister.tr(context: context),
onPressed: () async {
await authenticationViewModel.onLoginPressed();
},
backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA),
textColor: Color(0xffED1C2B),
fontSize: 16,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 50,
),
Utils.buildSvgWithAssets(
icon: AppAssets.contact_icon,
width: 24,
height: 24,
).onPress(() {
Navigator.of(context).push(
FadePage(
page: MedicalFilePage(),
// page: LoginScreen(),
),
);
}),
],
),
SizedBox(height: 16.h),
appState.isAuthenticated
? Column(
children: [
Container(
width: double.infinity,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24,
),
child: Padding(
padding: EdgeInsets.all(12.h),
child: Column(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.home_calendar_icon, width: 32.h, height: 32.h),
SizedBox(height: 12.h),
"You do not have any upcoming appointment. Please book an appointment".toText12(isCenter: true),
SizedBox(height: 12.h),
CustomButton(
text: LocaleKeys.bookAppo.tr(context: context),
onPressed: () {
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (BuildContext context) => LandingPage()),
);
},
backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA),
textColor: Color(0xffED1C2B),
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40,
icon: AppAssets.add_icon,
iconColor: AppColors.primaryRedColor,
),
],
),
),
),
SizedBox(height: 16.h),
appState.isAuthenticated
? Column(
children: [
Container(
width: double.infinity,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24,
),
SizedBox(height: 12.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Quick Links".toText16(isBold: true),
Row(
children: [
"View medical file".toText12(color: AppColors.primaryRedColor),
SizedBox(width: 2.h),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
],
),
],
child: Padding(
padding: EdgeInsets.all(12.h),
child: Column(
children: [
Utils.buildSvgWithAssets(icon: AppAssets.home_calendar_icon, width: 32.h, height: 32.h),
SizedBox(height: 12.h),
"You do not have any upcoming appointment. Please book an appointment".toText12(isCenter: true),
SizedBox(height: 12.h),
CustomButton(
text: LocaleKeys.bookAppo.tr(context: context),
onPressed: () {
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (BuildContext context) => LandingPage()),
);
},
backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA),
textColor: Color(0xffED1C2B),
fontSize: 14,
fontWeight: FontWeight.w500,
borderRadius: 12,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40,
icon: AppAssets.add_icon,
iconColor: AppColors.primaryRedColor,
),
],
),
),
SizedBox(height: 12.h),
Container(
height: 127.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24,
),
SizedBox(height: 12.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Quick Links".toText16(isBold: true),
Row(
children: [
"View medical file".toText12(color: AppColors.primaryRedColor),
SizedBox(width: 2.h),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
],
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
children: [
Expanded(
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: LandingPageData.getLoggedInServiceCardsList.length,
shrinkWrap: true,
padding: const EdgeInsets.only(left: 0, right: 8),
itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 1000),
child: SlideAnimation(
horizontalOffset: 100.0,
child: FadeInAnimation(
child: SmallServiceCard(
icon: LandingPageData.getLoggedInServiceCardsList[index].icon,
title: LandingPageData.getLoggedInServiceCardsList[index].title,
subtitle: LandingPageData.getLoggedInServiceCardsList[index].subtitle,
iconColor: LandingPageData.getLoggedInServiceCardsList[index].iconColor,
textColor: LandingPageData.getLoggedInServiceCardsList[index].textColor,
backgroundColor: LandingPageData.getLoggedInServiceCardsList[index].backgroundColor,
isBold: LandingPageData.getLoggedInServiceCardsList[index].isBold,
),
],
),
SizedBox(height: 12.h),
Container(
height: 127.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
children: [
Expanded(
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: LandingPageData.getLoggedInServiceCardsList.length,
shrinkWrap: true,
padding: const EdgeInsets.only(left: 0, right: 8),
itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 1000),
child: SlideAnimation(
horizontalOffset: 100.0,
child: FadeInAnimation(
child: SmallServiceCard(
icon: LandingPageData.getLoggedInServiceCardsList[index].icon,
title: LandingPageData.getLoggedInServiceCardsList[index].title,
subtitle: LandingPageData.getLoggedInServiceCardsList[index].subtitle,
iconColor: LandingPageData.getLoggedInServiceCardsList[index].iconColor,
textColor: LandingPageData.getLoggedInServiceCardsList[index].textColor,
backgroundColor: LandingPageData.getLoggedInServiceCardsList[index].backgroundColor,
isBold: LandingPageData.getLoggedInServiceCardsList[index].isBold,
),
),
);
},
separatorBuilder: (BuildContext cxt, int index) => 0.width,
),
),
);
},
separatorBuilder: (BuildContext cxt, int index) => 0.width,
),
],
),
),
],
),
)
],
)
: Container(
height: 127.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
children: [
Expanded(
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: LandingPageData.getNotLoggedInServiceCardsList.length,
shrinkWrap: true,
padding: const EdgeInsets.only(left: 0, right: 8),
itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 1000),
child: SlideAnimation(
horizontalOffset: 100.0,
child: FadeInAnimation(
child: SmallServiceCard(
icon: LandingPageData.getNotLoggedInServiceCardsList[index].icon,
title: LandingPageData.getNotLoggedInServiceCardsList[index].title,
subtitle: LandingPageData.getNotLoggedInServiceCardsList[index].subtitle,
iconColor: LandingPageData.getNotLoggedInServiceCardsList[index].iconColor,
textColor: LandingPageData.getNotLoggedInServiceCardsList[index].textColor,
backgroundColor: LandingPageData.getNotLoggedInServiceCardsList[index].backgroundColor,
isBold: LandingPageData.getNotLoggedInServiceCardsList[index].isBold,
),
),
)
],
)
: Container(
height: 127.h,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24,
),
child: Padding(
padding: EdgeInsets.all(16.h),
child: Column(
children: [
Expanded(
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: LandingPageData.getNotLoggedInServiceCardsList.length,
shrinkWrap: true,
padding: const EdgeInsets.only(left: 0, right: 8),
itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 1000),
child: SlideAnimation(
horizontalOffset: 100.0,
child: FadeInAnimation(
child: SmallServiceCard(
icon: LandingPageData.getNotLoggedInServiceCardsList[index].icon,
title: LandingPageData.getNotLoggedInServiceCardsList[index].title,
subtitle: LandingPageData.getNotLoggedInServiceCardsList[index].subtitle,
iconColor: LandingPageData.getNotLoggedInServiceCardsList[index].iconColor,
textColor: LandingPageData.getNotLoggedInServiceCardsList[index].textColor,
backgroundColor: LandingPageData.getNotLoggedInServiceCardsList[index].backgroundColor,
isBold: LandingPageData.getNotLoggedInServiceCardsList[index].isBold,
),
),
);
},
separatorBuilder: (BuildContext cxt, int index) => 0.width,
),
),
);
},
separatorBuilder: (BuildContext cxt, int index) => 0.width,
),
],
),
),
],
),
),
SizedBox(height: 16.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Services".toText16(isBold: true),
Row(
children: [
"View all services".toText12(color: AppColors.primaryRedColor),
SizedBox(width: 2.h),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
],
),
],
),
SizedBox(height: 16.h),
SizedBox(
height: 325.h,
child: Column(
SizedBox(height: 16.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Services".toText16(isBold: true),
Row(
children: [
Expanded(
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: LandingPageData.getServiceCardsList.length,
shrinkWrap: true,
padding: const EdgeInsets.only(left: 0, right: 8),
itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 1000),
child: SlideAnimation(
horizontalOffset: 100.0,
child: FadeInAnimation(
child: LargeServiceCard(
image: LandingPageData.getServiceCardsList[index].icon,
title: LandingPageData.getServiceCardsList[index].title,
subtitle: LandingPageData.getServiceCardsList[index].subtitle,
icon: LandingPageData.getServiceCardsList[index].largeCardIcon,
),
"View all services".toText12(color: AppColors.primaryRedColor),
SizedBox(width: 2.h),
Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h),
],
),
],
),
SizedBox(height: 16.h),
SizedBox(
height: 325.h,
child: Column(
children: [
Expanded(
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: LandingPageData.getServiceCardsList.length,
shrinkWrap: true,
padding: const EdgeInsets.only(left: 0, right: 8),
itemBuilder: (context, index) {
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 1000),
child: SlideAnimation(
horizontalOffset: 100.0,
child: FadeInAnimation(
child: LargeServiceCard(
image: LandingPageData.getServiceCardsList[index].icon,
title: LandingPageData.getServiceCardsList[index].title,
subtitle: LandingPageData.getServiceCardsList[index].subtitle,
icon: LandingPageData.getServiceCardsList[index].largeCardIcon,
),
),
);
},
separatorBuilder: (BuildContext cxt, int index) => 0.width,
),
),
);
},
separatorBuilder: (BuildContext cxt, int index) => 0.width,
),
],
),
),
],
),
SizedBox(height: 16.h),
appState.isAuthenticated ? HabibWalletCard() : SizedBox(),
],
),
),
SizedBox(height: 16.h),
appState.isAuthenticated ? HabibWalletCard() : SizedBox(),
],
),
),
);
});
),
);
}
}

@ -3,7 +3,7 @@ import 'package:hmg_patient_app_new/extensions/route_extensions.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
abstract class DialogService {
Future<void> showErrorDialog({required String message, Function()? onOkPressed});
Future<void> showErrorBottomSheet({required String message, Function()? onOkPressed});
}
class DialogServiceImp implements DialogService {
@ -12,7 +12,7 @@ class DialogServiceImp implements DialogService {
DialogServiceImp({required this.navigationService});
@override
Future<void> showErrorDialog({required String message, Function()? onOkPressed}) async {
Future<void> showErrorBottomSheet({required String message, Function()? onOkPressed}) async {
final context = navigationService.navigatorKey.currentContext;
if (context == null) return;

@ -2,6 +2,7 @@ import 'dart:io';
import 'package:hmg_patient_app_new/core/exceptions/api_exception.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/core/utils/loading_utils.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
@ -51,6 +52,9 @@ class ErrorHandlerServiceImp implements ErrorHandlerService {
}
Future<void> _showDialog(Failure failure, {String title = "Error", Function()? onOkPressed}) async {
await dialogService.showErrorDialog(message: failure.message, onOkPressed: onOkPressed);
if (LoadingUtils.isLoading) {
LoadingUtils.hideFullScreenLoader();
}
await dialogService.showErrorBottomSheet(message: failure.message, onOkPressed: onOkPressed);
}
}

@ -1,8 +1,6 @@
import 'package:logger/logger.dart';
abstract class LoggerService {
void errorLogs(String message);
void logInfo(String message);
@ -13,8 +11,6 @@ class LoggerServiceImp implements LoggerService {
LoggerServiceImp({required this.logger});
@override
void errorLogs(String message) {
logger.e(message);
@ -22,6 +18,6 @@ class LoggerServiceImp implements LoggerService {
@override
void logInfo(String message) {
logger.i(message);
logger.d(message);
}
}

@ -1,4 +1,5 @@
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
@ -25,6 +26,7 @@ class GenericBottomSheet extends StatefulWidget {
// FocusNode myFocusNode;
GenericBottomSheet({
super.key,
this.countryCode = "",
this.initialPhoneNumber = "",
required this.buttons,
@ -46,8 +48,8 @@ class _GenericBottomSheetState extends State<GenericBottomSheet> {
void initState() {
super.initState();
if (!widget.isForEmail) {
widget.textController = TextEditingController(text: widget.initialPhoneNumber);
if (!widget.isForEmail && widget.textController != null) {
widget.textController!.text = widget.initialPhoneNumber ?? "";
}
}

@ -80,14 +80,12 @@ class TextInputWidget extends StatelessWidget {
? CustomCountryDropdown(
countryList: CountryEnum.values,
onCountryChange: (CountryEnum? value) {
print(value);
},
isRtl: Directionality.of(context) == TextDirection.rtl,
isFromBottomSheet: isCountryDropDown,
isEnableTextField: true,
onPhoneNumberChanged: (value) {
print(value);
},
onPhoneNumberChanged:(val){},
textField: _buildTextField(context),
)
: Expanded(

Loading…
Cancel
Save