adding the login function

pull/12/head
faizatflutter 2 months ago
parent 32fadb8ad9
commit 6e05ca15cf

@ -134,9 +134,7 @@ class ApiClientImp implements ApiClient {
}
if (body.containsKey('isDentalAllowedBackend')) {
body['isDentalAllowedBackend'] = body.containsKey('isDentalAllowedBackend')
? body['isDentalAllowedBackend'] ?? IS_DENTAL_ALLOWED_BACKEND
: IS_DENTAL_ALLOWED_BACKEND;
body['isDentalAllowedBackend'] = body.containsKey('isDentalAllowedBackend') ? body['isDentalAllowedBackend'] ?? IS_DENTAL_ALLOWED_BACKEND : IS_DENTAL_ALLOWED_BACKEND;
}
//Todo: I have converted it to string
@ -204,9 +202,9 @@ class ApiClientImp implements ApiClient {
logApiEndpointError(endPoint, 'Error While Fetching data', statusCode);
} else {
var parsed = json.decode(utf8.decode(response.bodyBytes));
log("parsed: ${parsed.toString()}");
log("parsed: ${jsonEncode(parsed)}");
if (isAllowAny) {
onSuccess(parsed, statusCode);
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']);
} else {
if (parsed['Response_Message'] != null) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']);
@ -225,19 +223,18 @@ class ApiClientImp implements ApiClient {
if (parsed['isSMSSent'] == true) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']);
} else if (parsed['MessageStatus'] == 1) {
onSuccess(parsed, statusCode);
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']);
} else if (parsed['Result'] == 'OK') {
onSuccess(parsed, statusCode);
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']);
} else {
onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode,
failureType: ServerFailure("Error While Fetching data"));
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);
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']);
} else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) {
if (parsed['SameClinicApptList'] != null) {
onSuccess(parsed, statusCode);
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']);
} else {
if (parsed['message'] == null && parsed['ErrorEndUserMessage'] == null) {
if (parsed['ErrorSearchMsg'] == null) {
@ -266,7 +263,7 @@ class ApiClientImp implements ApiClient {
}
} else {
if (parsed['SameClinicApptList'] != null) {
onSuccess(parsed, statusCode);
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']);
} else {
if (parsed['message'] != null) {
onFailure(
@ -292,7 +289,7 @@ class ApiClientImp implements ApiClient {
onFailure(
'Please Check The Internet Connection 1',
-1,
failureType: ConnectivityFailure("Error While Fetching data"),
failureType: ConnectivityFailure("Please Check The Internet Connection 1"),
);
_analytics.errorTracking.log("internet_connectivity", error: "no internet available");
}

@ -747,6 +747,7 @@ class ApiConsts {
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';

@ -1,6 +1,7 @@
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;
@ -8,9 +9,11 @@ import 'api_consts.dart' as ApiConsts;
class AppState {
NavigationService navigationService;
AppState({required this.navigationService});
AppState({
required this.navigationService,
});
bool isAuthenticated = true;
bool isAuthenticated = false;
set setIsAuthenticated(v) => isAuthenticated = v;
@ -70,4 +73,16 @@ class AppState {
}
AuthenticatedUser? get getAuthenticatedUser => _authenticatedUser;
SelectDeviceByImeiRespModelElement? _selectDeviceByImeiRespModelElement;
void setSelectDeviceByImeiRespModelElement(SelectDeviceByImeiRespModelElement value) {
_selectDeviceByImeiRespModelElement = value;
}
SelectDeviceByImeiRespModelElement? get getSelectDeviceByImeiRespModelElement => _selectDeviceByImeiRespModelElement;
String appLoginToken = "";
set setAppLoginToken(v) => appLoginToken = v;
}

@ -43,7 +43,6 @@ class AppDependencies {
getIt.registerLazySingleton<NavigationService>(() => NavigationService());
getIt.registerLazySingleton<GAnalytics>(() => GAnalytics());
getIt.registerLazySingleton<AppState>(() => AppState(navigationService: getIt()));
getIt.registerLazySingleton<AppState>(() => AppState(navigationService: getIt()));
getIt.registerLazySingleton<LocationUtils>(() => LocationUtils(
isShowConfirmDialog: false,
navigationService: getIt(),

@ -28,7 +28,6 @@ enum LoginTypeEnum {
silentWithOTP,
}
enum OTPTypeEnum { sms, whatsapp }
enum CountryEnum { saudiArabia, unitedArabEmirates }
@ -40,6 +39,8 @@ enum MaritalStatusTypeEnum { single, married, divorced, widowed }
enum ChipTypeEnum { success, error, alert, info, warning }
enum OTPTypeEnum { sms, whatsapp }
extension OTPTypeEnumExtension on OTPTypeEnum {
/// Convert enum to int
int toInt() {

@ -0,0 +1,87 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:gif_view/gif_view.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
class LoadingUtils {
static final NavigationService _navigationService = getIt.get<NavigationService>();
static bool _isLoadingVisible = false;
static bool get isLoading => _isLoadingVisible;
static showFullScreenLoading({bool barrierDismissible = true}) {
if (!_isLoadingVisible) {
_isLoadingVisible = true;
final context = _navigationService.navigatorKey.currentContext;
log("context:$context");
if (context == null) return;
showDialog(
barrierDismissible: barrierDismissible,
context: context,
barrierColor: AppColors.blackColor.withOpacity(0.5),
useRootNavigator: false,
builder: (BuildContext context) => Center(
child: CircularProgressIndicator(
color: AppColors.primaryRedColor,
)),
).then((value) {
_isLoadingVisible = false;
});
}
}
static hideFullScreenLoader() {
if (!_isLoadingVisible) return;
final context = _navigationService.navigatorKey.currentContext;
if (context != null) {
try {
Navigator.of(context).pop();
} catch (_) {}
}
_isLoadingVisible = false;
}
}
class GifLoaderContainer extends StatefulWidget {
final bool barrierDismissible;
const GifLoaderContainer({super.key, this.barrierDismissible = true});
@override
GifLoaderContainerState createState() => GifLoaderContainerState();
}
class GifLoaderContainerState extends State<GifLoaderContainer> with TickerProviderStateMixin {
late GifController controller;
@override
void initState() {
super.initState();
controller = GifController();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return PopScope(
canPop: widget.barrierDismissible,
child: Center(
child: GifView(
controller: controller,
image: AssetImage("assets/images/progress-loading-red.gif"),
),
),
);
}
}

@ -1,3 +1,5 @@
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';
@ -17,6 +19,7 @@ class RequestUtils {
if (nationIdText.isNotEmpty) {
fileNo = nationIdText.length < 10;
}
log("phoneNumber: ${phoneNumber}");
var request = SendActivationRequest();
request.patientMobileNumber = int.parse(phoneNumber);
request.mobileNo = '0$phoneNumber';

@ -1,4 +1,5 @@
import 'dart:convert';
import 'dart:developer';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:crypto/crypto.dart' as crypto;
@ -13,7 +14,6 @@ import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/services/dialog_service.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/dialogs/confirm_dialog.dart';
@ -59,14 +59,12 @@ class Utils {
// ),
// ));
return !isAddHours
? DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US")
.format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.toLocal())
: DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US")
.format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.add(
Duration(
hours: isAddHours ? 3 : 0,
),
));
? DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US").format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.toLocal())
: DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US").format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.add(
Duration(
hours: isAddHours ? 3 : 0,
),
));
}
static String convertStringToDateTime(String dateTimeString) {
@ -205,16 +203,16 @@ class Utils {
_isLoadingVisible = true;
showDialog(
context: navigationService.navigatorKey.currentContext!,
barrierColor: Colors.black.withOpacity(0.5),
barrierColor: AppColors.blackColor,
builder: (BuildContext context) => LoadingDialog(),
)
.then((value) {
_isLoadingVisible = false;
})
_isLoadingVisible = false;
})
.catchError((e) {})
.onError(
(error, stackTrace) {},
);
);
}
static void hideLoading() {
@ -224,7 +222,9 @@ class Utils {
Navigator.of(navigationService.navigatorKey.currentContext!).pop();
}
_isLoadingVisible = false;
} catch (e) {}
} catch (e) {
log("errr: ${e.toString()}");
}
}
static List<T> uniqueBy<T, K>(List<T> list, K Function(T) keySelector) {
@ -236,12 +236,11 @@ class Utils {
showDialog(
barrierDismissible: false,
context: context,
builder: (cxt) =>
ConfirmDialog(
title: title!,
message: message!,
onTap: onTap,
),
builder: (cxt) => ConfirmDialog(
title: title!,
message: message!,
onTap: onTap,
),
);
}
@ -268,7 +267,7 @@ class Utils {
var x = int.parse(a) * 2;
var b = x.toString();
if (b.length == 1) {
b = "0" + b;
b = "0$b";
}
sum += int.parse(b[0]) + int.parse(b[1]);
} else {
@ -277,7 +276,9 @@ class Utils {
}
return sum % 10 == 0;
}
} catch (err) {}
} catch (err) {
log("errr: ${err.toString()}");
}
return false;
} else {
return true;
@ -311,10 +312,8 @@ class Utils {
}
// Replace HTML line breaks with newlines
var withLineBreaks = htmlString
.replaceAll(RegExp(r'<br\s*\/?>', multiLine: true), '\n')
.replaceAll(RegExp(r'<\/p>', multiLine: true), '\n')
.replaceAll(RegExp(r'<divider>', multiLine: true), '\n');
var withLineBreaks =
htmlString.replaceAll(RegExp(r'<br\s*\/?>', multiLine: true), '\n').replaceAll(RegExp(r'<\/p>', multiLine: true), '\n').replaceAll(RegExp(r'<divider>', multiLine: true), '\n');
// Remove all other HTML tags
var withoutTags = withLineBreaks.replaceAll(RegExp(r'<[^>]*>'), '');
@ -362,9 +361,8 @@ class Utils {
final month = monthNames[dateTime.month - 1];
return '$day $month, $year';
return '$day $month, $year';
} catch (e) {
print("Error formatting date: $e");
log("Error formatting date: $e");
return "";
}
}
@ -372,9 +370,7 @@ class Utils {
static String formatHijriDateToDisplay(String hijriDateString) {
try {
// Assuming hijriDateString is in the format yyyy-MM-dd
final datePart = hijriDateString
.split("T")
.first;
final datePart = hijriDateString.split("T").first;
final parts = datePart.split('-');
if (parts.length != 3) return "";
@ -382,26 +378,13 @@ class Utils {
final year = parts[0];
// Map month number to short month name (Hijri months)
const hijriMonthNames = [
'Muharram',
'Safar',
'Rabi I',
'Rabi II',
'Jumada I',
'Jumada II',
'Rajab',
'Sha\'ban',
'Ramadan',
'Shawwal',
'Dhu al-Qi\'dah',
'Dhu al-Hijjah'
];
const hijriMonthNames = ['Muharram', 'Safar', 'Rabi I', 'Rabi II', 'Jumada I', 'Jumada II', 'Rajab', 'Sha\'ban', 'Ramadan', 'Shawwal', 'Dhu al-Qi\'dah', 'Dhu al-Hijjah'];
final monthIndex = int.tryParse(parts[1]) ?? 1;
final month = hijriMonthNames[monthIndex - 1];
return '$day $month, $year';
} catch (e) {
print("Error formatting hijri date: $e");
log("Error formatting hijri date: $e");
return "";
}
}
@ -415,7 +398,7 @@ class Utils {
return '$day-$month-$year';
} catch (e) {
print("Error formatting date: $e");
log("Error formatting date: $e");
return "";
}
}
@ -432,14 +415,8 @@ class Utils {
void Function(LottieComposition)? onLoaded,
}) {
return Lottie.asset(assetPath,
height: height ?? MediaQuery
.of(context)
.size
.height * 0.26,
width: width ?? MediaQuery
.of(context)
.size
.width,
height: height ?? MediaQuery.of(context).size.height * 0.26,
width: width ?? MediaQuery.of(context).size.width,
fit: fit,
alignment: alignment,
repeat: repeat,
@ -499,10 +476,7 @@ class Utils {
static Future<bool> isGoogleServicesAvailable() async {
GooglePlayServicesAvailability availability = await GoogleApiAvailability.instance.checkGooglePlayServicesAvailability();
String status = availability
.toString()
.split('.')
.last;
String status = availability.toString().split('.').last;
if (status == "success") {
return true;
}
@ -523,26 +497,3 @@ class Utils {
return crypto.md5.convert(utf8.encode(input)).toString();
}
}
class ValidationUtils {
static DialogService dialogService = getIt.get<DialogService>();
static bool isValidatePhoneAndId({
String? nationalId,
String? phoneNumber
}) {
if (nationalId == null || nationalId.isEmpty) {
dialogService.showErrorDialog(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: () {});
return false;
}
return true;
}
}

@ -0,0 +1,19 @@
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
class ValidationUtils {
static final DialogService _dialogService = getIt.get<DialogService>();
static bool isValidatePhoneAndId({String? nationalId, String? phoneNumber}) {
if (nationalId == null || nationalId.isEmpty) {
_dialogService.showErrorDialog(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: () {});
return false;
}
return true;
}
}

@ -6,7 +6,6 @@ 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/request_models/check_patient_authentication_request_model.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';
@ -16,12 +15,10 @@ abstract class AuthenticationRepo {
required String firebaseToken,
});
Future<Either<Failure, GenericApiModel<dynamic>>> checkPatientAuthentication({
required CheckPatientAuthenticationReq checkPatientAuthenticationReq,
});
Future<Either<Failure, GenericApiModel<dynamic>>> checkPatientAuthentication({required dynamic checkPatientAuthenticationReq});
Future<Either<Failure, GenericApiModel<dynamic>>> sendActivationCodeRepo({
required CheckPatientAuthenticationReq checkPatientAuthenticationReq,
required dynamic checkPatientAuthenticationReq,
String? languageID,
bool isRegister = false,
});
@ -80,7 +77,7 @@ class AuthenticationRepoImp implements AuthenticationRepo {
@override
Future<Either<Failure, GenericApiModel<dynamic>>> checkPatientAuthentication({
required CheckPatientAuthenticationReq checkPatientAuthenticationReq,
required dynamic checkPatientAuthenticationReq,
String? languageID,
}) async {
int isOutKsa = (checkPatientAuthenticationReq.zipCode == '966' || checkPatientAuthenticationReq.zipCode == '+966') ? 0 : 1;
@ -96,7 +93,7 @@ class AuthenticationRepoImp implements AuthenticationRepo {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
ApiConsts.selectDeviceImei,
ApiConsts.checkPatientAuth,
body: checkPatientAuthenticationReq.toJson(),
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
@ -124,7 +121,7 @@ class AuthenticationRepoImp implements AuthenticationRepo {
@override
Future<Either<Failure, GenericApiModel<dynamic>>> sendActivationCodeRepo({
required CheckPatientAuthenticationReq checkPatientAuthenticationReq,
required dynamic checkPatientAuthenticationReq,
String? languageID,
bool isRegister = false,
}) async {

@ -1,12 +1,13 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_export.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/cache_consts.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';
import 'package:hmg_patient_app_new/features/authentication/authentication_repo.dart';
import 'package:hmg_patient_app_new/features/authentication/models/request_models/check_patient_authentication_request_model.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/presentation/authentication/login.dart';
@ -16,31 +17,28 @@ import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
class AuthenticationViewModel extends ChangeNotifier {
AuthenticationRepo authenticationRepo;
AppState appState;
ErrorHandlerService errorHandlerService;
DialogService dialogService;
NavigationService navigationService;
CacheService cacheService;
final AuthenticationRepo _authenticationRepo;
final AppState _appState;
final ErrorHandlerService _errorHandlerService;
final DialogService _dialogService;
final NavigationService _navigationService;
AuthenticationViewModel({
required this.appState,
required this.authenticationRepo,
required this.errorHandlerService,
required this.dialogService,
required this.navigationService,
required this.cacheService,
});
required AppState appState,
required AuthenticationRepo authenticationRepo,
required ErrorHandlerService errorHandlerService,
required DialogService dialogService,
required NavigationService navigationService,
required CacheService cacheService,
}) : _navigationService = navigationService,
_dialogService = dialogService,
_errorHandlerService = errorHandlerService,
_appState = appState,
_authenticationRepo = authenticationRepo;
final TextEditingController nationalIdController = TextEditingController();
final TextEditingController phoneNumberController = TextEditingController();
void login() {
if (ValidationUtils.isValidatePhoneAndId(nationalId: nationalIdController.text, phoneNumber: phoneNumberController.text)) {
} else {}
}
//checkUserAuthentication();
bool isDubai = false;
bool authenticated = false;
late int mobileNumber;
@ -61,106 +59,141 @@ class AuthenticationViewModel extends ChangeNotifier {
late int isHijri;
var healthId;
Future<void> onLoginPressed() async {
try {
LoadingUtils.showFullScreenLoading();
//TODO: We will remove this delay
await Future.delayed(Duration(seconds: 3));
var data = _appState.getSelectDeviceByImeiRespModelElement;
log("Cached IMEI data: ${data?.toJson()}");
if (data != null) {
await _handleExistingImeiData(data);
} else {
await _handleNewImeiRegistration();
}
} catch (e) {
log("Error in onLoginPressed: $e");
LoadingUtils.hideFullScreenLoader();
_dialogService.showErrorDialog(message: "An unexpected error occurred. Please try again.", onOkPressed: () {});
}
}
Future<void> selectDeviceImei({required Function(dynamic data) onSuccess, Function(String)? onError}) async {
String firebaseToken = appState.deviceToken == ""
// LoadingUtils.showFullScreenLoading();
String firebaseToken = _appState.deviceToken == ""
? "dOGRRszQQMGe_9wA5Hx3kO:APA91bFV5IcIJXvcCXXk0tc2ddtZgWwCPq7sGSuPr-YW7iiJpQZKgFGN9GAzCVOWL8MfheaP1slE8MdxB7lczdPBGdONQ7WbMmhgHcsUCUktq-hsapGXXqc"
: appState.deviceToken;
final result = await authenticationRepo.selectDeviceByImei(firebaseToken: firebaseToken);
: _appState.deviceToken;
final result = await _authenticationRepo.selectDeviceByImei(firebaseToken: firebaseToken);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(failure) async {
// LoadingUtils.hideFullScreenLoader();
await _errorHandlerService.handleError(failure: failure);
},
(apiResponse) {
// LoadingUtils.hideFullScreenLoader();
log("apiResponse: ${apiResponse.data.toString()}");
log("messageStatus: ${apiResponse.messageStatus.toString()}");
if (apiResponse.messageStatus == 1) {
onSuccess(apiResponse.data);
} else if (apiResponse.messageStatus == 2) {
dialogService.showErrorDialog(message: "Message Status = 2", onOkPressed: () {});
_dialogService.showErrorDialog(message: "Message Status = 2", onOkPressed: () {});
}
},
);
}
Future<void> onLoginPressed() async {
var data = await cacheService.getObject(key: CacheConst.imeiUserData);
//TODO: Why???
cacheService.remove(key: CacheConst.registerDataForLogin);
if (data != null) {
SelectDeviceByImeiRespModelElement savedData = SelectDeviceByImeiRespModelElement.fromJson(data);
// TODO : SavedLogin Page is not there or renamed.
// navigationService.pushPage(page: SavedLogin(savedData));
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (BuildContext context) => SavedLogin(savedData),
// ),
// );
} else {
// Todo: Show Loader Here
// GifLoaderDialogUtils.showMyDialog(context);
selectDeviceImei(
onSuccess: (dynamic respData) async {
var data = await cacheService.getObject(key: CacheConst.imeiUserData);
if (respData != null) {
cacheService.saveObject(key: CacheConst.imeiUserData, value: respData);
Future<void> _handleExistingImeiData(dynamic data) async {
try {
SelectDeviceByImeiRespModelElement? savedData = _appState.getSelectDeviceByImeiRespModelElement;
LoadingUtils.hideFullScreenLoader();
// SelectDeviceByImeiRespModelElement savedData = SelectDeviceByImeiRespModelElement.fromJson(data);
// setUserValues(value);
// TODO : SavedLogin Page is not there or renamed.
// navigationService.pushPage(page: SavedLogin(savedData));
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (BuildContext context) => SavedLogin(savedData),
// ),
// );
} else {
//Todo: Hide Loader Here
// GifLoaderDialogUtils.hideDialog(context);
navigationService.pushPage(page: LoginScreen());
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (BuildContext context) => WelcomeLogin(),
// ),
// );
}
},
);
if (savedData != null) {
// TODO: Navigate to SavedLogin when available
_navigationService.pushPage(page: LoginScreen());
// navigationService.pushPage(page: SavedLogin(savedData));
}
} catch (e) {
log("Error handling existing IMEI data: $e");
LoadingUtils.hideFullScreenLoader();
_navigationService.pushPage(page: LoginScreen());
}
}
Future<void> _handleNewImeiRegistration() async {
await selectDeviceImei(onSuccess: (dynamic respData) async {
try {
if (respData != null) {
dynamic data = SelectDeviceByImeiRespModelElement.fromJson(respData.toJson());
_appState.setSelectDeviceByImeiRespModelElement(data);
LoadingUtils.hideFullScreenLoader();
// TODO: Navigate to SavedLogin when available
// SelectDeviceByImeiRespModelElement savedData =
// SelectDeviceByImeiRespModelElement.fromJson(respData);
// navigationService.pushPage(page: SavedLogin(savedData));
_navigationService.pushPage(page: LoginScreen());
} else {
LoadingUtils.hideFullScreenLoader();
_navigationService.pushPage(page: LoginScreen());
}
} catch (e) {
log("Error processing IMEI registration response: $e");
LoadingUtils.hideFullScreenLoader();
_navigationService.pushPage(page: LoginScreen());
}
}, onError: (String error) {
LoadingUtils.hideFullScreenLoader();
_dialogService.showErrorDialog(message: error, onOkPressed: () {});
});
}
Future<void> checkUserAuthentication({required OTPTypeEnum otpTypeEnum, Function(dynamic)? onSuccess, Function(String)? onError}) async {
CheckPatientAuthenticationReq checkPatientAuthenticationReq = RequestUtils.getCommonRequestWelcome(
phoneNumber: '0567184134',
otpTypeEnum: OTPTypeEnum.sms,
// 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
bool isValidated = ValidationUtils.isValidatePhoneAndId(
phoneNumber: phoneNumberController.text,
nationalId: nationalIdController.text,
);
if (!isValidated) return;
dynamic checkPatientAuthenticationReq = RequestUtils.getCommonRequestWelcome(
phoneNumber: phoneNumberController.text,
nationIdText: nationalIdController.text,
otpTypeEnum: otpTypeEnum,
deviceToken: 'dummyDeviceToken123',
patientOutSA: true,
loginTokenID: 'dummyLoginToken456',
registeredData: null,
patientId: 12345,
nationIdText: '1234567890',
countryCode: 'SA',
);
final result = await authenticationRepo.checkPatientAuthentication(checkPatientAuthenticationReq: checkPatientAuthenticationReq);
final result = await _authenticationRepo.checkPatientAuthentication(checkPatientAuthenticationReq: checkPatientAuthenticationReq);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(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);
checkActivationCode(
onWrongActivationCode: (String? message) {},
activationCode: 0000,
);
}
}
},
);
}
Future<void> sendActivationCode({
required OTPTypeEnum otpTypeEnum,
}) async {
Future<void> sendActivationCode({required OTPTypeEnum otpTypeEnum}) async {
var request = RequestUtils.getCommonRequestAuthProvider(
otpTypeEnum: otpTypeEnum,
registeredData: null,
@ -190,13 +223,13 @@ class AuthenticationViewModel extends ChangeNotifier {
request.isHijri = 0;
}
final resultEither = await authenticationRepo.sendActivationCodeRepo(
final resultEither = await _authenticationRepo.sendActivationCodeRepo(
checkPatientAuthenticationReq: request,
isRegister: isForRegister,
languageID: 'er',
);
resultEither.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(failure) async => await _errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.data != null && apiResponse.data['isSMSSent'] == true) {
// startSMSService(otpTypeEnum.toInt());
@ -229,30 +262,30 @@ class AuthenticationViewModel extends ChangeNotifier {
request['HealthId'] = healthId;
request['IsHijri'] = isHijri;
final resultEither = await authenticationRepo.checkActivationCodeRepo(
final resultEither = await _authenticationRepo.checkActivationCodeRepo(
newRequest: request,
activationCode: activationCode.toString(),
isRegister: true,
);
res = resultEither;
resultEither.fold((failure) async => await errorHandlerService.handleError(failure: failure), (apiResponse) {
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) {
final activation = CheckActivationCode.fromJson(apiResponse.data as Map<String, dynamic>);
if (registerd_data?.isRegister == true) {
navigationService.popUntilNamed(AppRoutes.registerNewScreen);
_navigationService.popUntilNamed(AppRoutes.registerNewScreen);
// Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew));
return;
}
});
} else {
final resultEither = await authenticationRepo.checkActivationCodeRepo(
final resultEither = await _authenticationRepo.checkActivationCodeRepo(
newRequest: request,
activationCode: activationCode.toString(),
isRegister: false,
);
res = resultEither;
resultEither.fold((failure) async => await errorHandlerService.handleError(failure: failure), (apiResponse) {
resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) {
final activation = CheckActivationCode.fromJson(resultEither as Map<String, dynamic>);
if (activation.errorCode == '699') {
// Todo: Hide Loader
@ -260,7 +293,7 @@ class AuthenticationViewModel extends ChangeNotifier {
onWrongActivationCode(activation.errorEndUserMessage);
return;
} else if (registerd_data?.isRegister == true) {
navigationService.popUntilNamed(AppRoutes.registerNewScreen);
_navigationService.popUntilNamed(AppRoutes.registerNewScreen);
// Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew));
return;
} else {
@ -284,7 +317,7 @@ class AuthenticationViewModel extends ChangeNotifier {
}
Future<void> navigateToOTPScreen({required OTPTypeEnum otpTypeEnum, required String phoneNumber}) async {
navigationService.pushToOtpScreen(
_navigationService.pushToOtpScreen(
phoneNumber: phoneNumber,
checkActivationCode: (int activationCode) async {
await checkActivationCode(
@ -300,4 +333,12 @@ class AuthenticationViewModel extends ChangeNotifier {
Future<void> onWrongActivationCode({String? message}) async {
// TODO: HANDLE THIS VIA BOTTOM SHEET
}
@override
void dispose() {
nationalIdController.dispose();
phoneNumberController.dispose();
myFocusNode.dispose();
super.dispose();
}
}

@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/context_extensions.dart';
@ -18,6 +19,8 @@ import 'package:hmg_patient_app_new/widgets/input_widget.dart';
import 'package:provider/provider.dart';
class LoginScreen extends StatefulWidget {
const LoginScreen({super.key});
@override
_LoginScreen createState() => _LoginScreen();
}
@ -83,7 +86,7 @@ class _LoginScreen extends State<LoginScreen> {
icon: AppAssets.login1,
iconColor: Colors.white,
onPressed: () {
showLoginModel(context: context, textController: authVm.phoneNumberController);
showLoginModelSheet(context: context, textController: authVm.phoneNumberController, authViewModel: authVm);
// if (nationIdController.text.isNotEmpty) {
// } else {
@ -140,12 +143,16 @@ class _LoginScreen extends State<LoginScreen> {
);
}
void showLoginModel({required BuildContext context, TextEditingController? textController}) {
void showLoginModelSheet({
required BuildContext context,
required TextEditingController? textController,
required AuthenticationViewModel authViewModel,
}) {
context.showBottomSheet(
isScrollControlled: true,
isDismissible: false,
useSafeArea: true,
backgroundColor: Colors.transparent,
backgroundColor: AppColors.transparent,
child: StatefulBuilder(builder: (BuildContext context, StateSetter setModalState) {
return Padding(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
@ -162,7 +169,9 @@ class _LoginScreen extends State<LoginScreen> {
padding: EdgeInsets.only(bottom: 10.h),
child: CustomButton(
text: LocaleKeys.sendOTPSMS.tr(),
onPressed: () {},
onPressed: () async {
await authViewModel.checkUserAuthentication(otpTypeEnum: OTPTypeEnum.sms);
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedBorderColor,
textColor: AppColors.whiteColor,
@ -183,7 +192,9 @@ class _LoginScreen extends State<LoginScreen> {
padding: EdgeInsets.only(bottom: 10.h, top: 10.h),
child: CustomButton(
text: LocaleKeys.sendOTPWHATSAPP.tr(),
onPressed: () {},
onPressed: () async {
await authViewModel.checkUserAuthentication(otpTypeEnum: OTPTypeEnum.whatsapp);
},
backgroundColor: Colors.white,
borderColor: AppColors.borderOnlyColor,
textColor: AppColors.textColor,

@ -11,13 +11,13 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/authentication/login.dart';
import 'package:hmg_patient_app_new/presentation/home/data/landing_page_data.dart';
import 'package:hmg_patient_app_new/presentation/home/widgets/habib_wallet_card.dart';
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/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart';
@ -34,6 +34,7 @@ class _LandingPageState extends State<LandingPage> {
@override
Widget build(BuildContext context) {
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(
@ -51,8 +52,7 @@ class _LandingPageState extends State<LandingPage> {
CustomButton(
text: LocaleKeys.loginOrRegister.tr(context: context),
onPressed: () async {
// await authenticationViewModel.selectDeviceImei();
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => LoginScreen()));
await authenticationViewModel.onLoginPressed();
},
backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA),

@ -45,6 +45,7 @@ class ErrorHandlerServiceImp implements ErrorHandlerService {
await _showDialog(failure, title: "Unknown Error");
} else {
loggerService.errorLogs("Unhandled failure type: $failure");
await _showDialog(failure, title: "Error");
}
}

@ -654,6 +654,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "8.2.0"
gif_view:
dependency: "direct main"
description:
name: gif_view
sha256: "4c7e17c134719531dabab54af121e4600d63283f56f3aff57c16db54766b67bc"
url: "https://pub.dev"
source: hosted
version: "1.0.3"
google_api_availability:
dependency: "direct main"
description:
@ -874,26 +882,26 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0"
url: "https://pub.dev"
source: hosted
version: "10.0.9"
version: "11.0.1"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.dev"
source: hosted
version: "3.0.9"
version: "3.0.10"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
version: "3.0.2"
lints:
dependency: transitive
description:
@ -1455,10 +1463,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
url: "https://pub.dev"
source: hosted
version: "0.7.4"
version: "0.7.6"
time:
dependency: transitive
description:
@ -1583,10 +1591,10 @@ packages:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.dev"
source: hosted
version: "2.1.4"
version: "2.2.0"
vm_service:
dependency: transitive
description:
@ -1636,5 +1644,5 @@ packages:
source: hosted
version: "6.5.0"
sdks:
dart: ">=3.7.0 <4.0.0"
dart: ">=3.8.0-0 <4.0.0"
flutter: ">=3.29.0"

@ -64,6 +64,7 @@ dependencies:
equatable: ^2.0.7
google_api_availability: ^5.0.1
firebase_analytics: ^11.5.1
gif_view: ^1.0.3
web: any
flutter_staggered_animations: ^1.1.1

Loading…
Cancel
Save