Merge branch 'faiz_dev' into faiz_dev1
# Conflicts: # ios/Podfile.lock # lib/main.dart # lib/routes/app_routes.dart # pubspec.lockpull/3/head
						commit
						cbfb381615
					
				| @ -1,9 +1,31 @@ | ||||
| import 'package:get_it/get_it.dart'; | ||||
| import 'package:hmg_patient_app_new/core/api/api_client.dart'; | ||||
| import 'package:hmg_patient_app_new/core/app_state.dart'; | ||||
| import 'package:injector/injector.dart'; | ||||
| import 'package:hmg_patient_app_new/features/authentication/authentication_repo.dart'; | ||||
| import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_repo.dart'; | ||||
| import 'package:hmg_patient_app_new/features/common/common_repo.dart'; | ||||
| import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_repo.dart'; | ||||
| import 'package:hmg_patient_app_new/services/cache_service.dart'; | ||||
| import 'package:hmg_patient_app_new/services/logger_service.dart'; | ||||
| import 'package:logger/web.dart'; | ||||
| import 'package:shared_preferences/shared_preferences.dart'; | ||||
| 
 | ||||
| GetIt getIt = GetIt.instance; | ||||
| 
 | ||||
| class AppDependencies { | ||||
|   static void addDependencies() { | ||||
|     Injector injector = Injector.appInstance; | ||||
|     injector.registerSingleton<AppState>(() => AppState()); | ||||
|   static Future<void> addDependencies() async { | ||||
|     // Services | ||||
|     getIt.registerLazySingleton<LoggerService>(() => LoggerServiceImp(logger: Logger(printer: PrettyPrinter(lineLength: 0)))); | ||||
|     final sharedPreferences = await SharedPreferences.getInstance(); | ||||
|     getIt.registerLazySingleton<CacheService>(() => CacheServiceImp(sharedPreferences: sharedPreferences)); | ||||
|     getIt.registerSingleton(AppState()); | ||||
|     getIt.registerLazySingleton<ApiClient>(() => ApiClient(loggerService: getIt())); | ||||
| 
 | ||||
|     // Repositories | ||||
|     getIt.registerLazySingleton<CommonRepo>(() => CommonRepoImp(loggerService: getIt())); | ||||
|     getIt.registerLazySingleton<AuthenticationRepo>(() => AuthenticationRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt())); | ||||
|     getIt.registerLazySingleton<BookAppointmentsRepo>(() => BookAppointmentsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt())); | ||||
|     getIt.registerLazySingleton<MyAppointmentsRepo>(() => MyAppointmentsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt())); | ||||
| 
 | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -0,0 +1,42 @@ | ||||
| 
 | ||||
| import 'package:equatable/equatable.dart'; | ||||
| 
 | ||||
| abstract class Failure extends Equatable implements Exception { | ||||
|   final String message; | ||||
|   const Failure(this.message); | ||||
| } | ||||
| 
 | ||||
| class ServerFailure extends Failure { | ||||
|   const ServerFailure(super.message); | ||||
| 
 | ||||
|   @override | ||||
|   List<Object?> get props => [message]; | ||||
| } | ||||
| 
 | ||||
| class ConnectivityFailure extends Failure { | ||||
|   const ConnectivityFailure(super.message); | ||||
| 
 | ||||
|   @override | ||||
|   List<Object?> get props => [message]; | ||||
| } | ||||
| 
 | ||||
| class LocalStorageFailure extends Failure { | ||||
|   const LocalStorageFailure(super.message); | ||||
| 
 | ||||
|   @override | ||||
|   List<Object?> get props => [message]; | ||||
| } | ||||
| 
 | ||||
| class DuplicateUsername extends Failure { | ||||
|   const DuplicateUsername({String? message}) : super(message ?? ''); | ||||
| 
 | ||||
|   @override | ||||
|   List<Object?> get props => [message]; | ||||
| } | ||||
| 
 | ||||
| class InvalidCredentials extends Failure { | ||||
|   const InvalidCredentials({String? message}) : super(message ?? ''); | ||||
| 
 | ||||
|   @override | ||||
|   List<Object?> get props => [message]; | ||||
| } | ||||
| @ -0,0 +1,23 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| 
 | ||||
| extension NavigationExtensions on BuildContext { | ||||
|   void navigateWithName(String routeName, {Object? arguments}) { | ||||
|     Navigator.pushNamed(this, routeName, arguments: arguments); | ||||
|   } | ||||
| 
 | ||||
|   Future<void> navigateReplaceWithName(String routeName, {Object? arguments}) async { | ||||
|     await Navigator.pushReplacementNamed(this, routeName, arguments: arguments); | ||||
|   } | ||||
| 
 | ||||
|   void navigateReplaceWithNameUntilRoute(String routeName, {Object? arguments}) { | ||||
|     Navigator.pushNamedAndRemoveUntil(this, routeName, (route) => false); | ||||
|   } | ||||
| 
 | ||||
|   void pop() { | ||||
|     Navigator.of(this).pop(); | ||||
|   } | ||||
| 
 | ||||
|   void navigateTo(Widget page) { | ||||
|     Navigator.push(this, MaterialPageRoute(builder: (context) => page)); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,44 @@ | ||||
| import 'package:dartz/dartz.dart'; | ||||
| import 'package:hmg_patient_app_new/core/api/api_client.dart'; | ||||
| 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/features/authentication/models/select_device_by_imei.dart'; | ||||
| import 'package:hmg_patient_app_new/services/logger_service.dart'; | ||||
| import 'package:http/http.dart'; | ||||
| 
 | ||||
| abstract class AuthenticationRepo { | ||||
|   Future<Either<Failure, SelectDeviceByImeiRespModelElement?>> selectDeviceByImei({required String deviceIMEI}); | ||||
| } | ||||
| 
 | ||||
| class AuthenticationRepoImp implements AuthenticationRepo { | ||||
|   final ApiClient apiClient; | ||||
|   final LoggerService loggerService; | ||||
| 
 | ||||
|   AuthenticationRepoImp({required this.loggerService, required this.apiClient}); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Either<Failure, SelectDeviceByImeiRespModelElement?>> selectDeviceByImei({required String deviceIMEI}) async { | ||||
|     final mapDevice = {"": deviceIMEI}; | ||||
| 
 | ||||
|     final String apiUrl = "https://hmgwebservices.com/Services/Patients.svc/REST/Patient_SELECTDeviceIMEIbyIMEI" ; | ||||
|     try { | ||||
|       final Response result = await apiClient.postJsonForResponse(apiUrl, mapDevice); | ||||
|       if (result !=null) { | ||||
|         return Right(null); | ||||
|       } else { | ||||
|         loggerService.errorLogs(result.toString()); | ||||
|         return Left(ServerFailure(result.toString())); | ||||
|       } | ||||
|     } on APIException catch (e) { | ||||
|       APIError? apiError; | ||||
|       if (e.error is APIError) { | ||||
|         apiError = e.error as APIError; | ||||
|       } | ||||
|       loggerService.errorLogs(e.toString()); | ||||
|       return Left(ServerFailure(apiError?.errorMessage ?? e.message)); | ||||
|     } catch (e) { | ||||
|       loggerService.errorLogs(e.toString()); | ||||
|       return Left(ServerFailure(e.toString())); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,47 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:hmg_patient_app_new/core/utils/utils.dart'; | ||||
| import 'package:hmg_patient_app_new/features/authentication/authentication_repo.dart'; | ||||
| 
 | ||||
| class AuthenticationViewModel extends ChangeNotifier { | ||||
|   AuthenticationRepo authenticationRepo; | ||||
| 
 | ||||
|   AuthenticationViewModel({required this.authenticationRepo}); | ||||
| 
 | ||||
| 
 | ||||
|    | ||||
|   Future<void> signUp({ | ||||
|     required String phone, | ||||
|     required String password, | ||||
|     Function(dynamic)? onSuccess, | ||||
|     Function(String)? onError, | ||||
|   }) async { | ||||
|     Utils.showLoading(); | ||||
|     final String deviceIMEI = | ||||
|         "cIkkB7h7Q7uoFkC4Qv82xG:APA91bEb53Z9XzqymCIctaLxCoMX6bm9fuKlWILQ59uUqfwhCoD42AOP1-jWGB1WYd9BVN5PT2pUUFxrT07vcNg1KH9OH39mrPgCl0m21XVIgWrzNnCkufg"; | ||||
| 
 | ||||
|     final resultEither = await authenticationRepo.selectDeviceByImei(deviceIMEI: deviceIMEI); | ||||
| 
 | ||||
|     if (resultEither.isLeft()) { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     if (resultEither.isRight()) { | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     resultEither.fold( | ||||
|       (failure) { | ||||
|         Utils.hideLoading(); | ||||
|         notifyListeners(); | ||||
|         if (onError != null) onError(failure.message); | ||||
|       }, | ||||
|       (data) { | ||||
| 
 | ||||
|         notifyListeners(); | ||||
|         if (onSuccess != null) onSuccess(data); | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,77 @@ | ||||
| // To parse this JSON data, do | ||||
| // | ||||
| //     final selectDeviceByImeiRespModel = selectDeviceByImeiRespModelFromJson(jsonString); | ||||
| 
 | ||||
| import 'dart:convert'; | ||||
| 
 | ||||
| Map<String, dynamic> selectDeviceByImeiRespModelFromJson(String str) => Map.from(json.decode(str)).map((k, v) => MapEntry<String, dynamic>(k, v)); | ||||
| 
 | ||||
| String selectDeviceByImeiRespModelToJson(Map<String, dynamic> data) => json.encode(Map.from(data).map((k, v) => MapEntry<String, dynamic>(k, v))); | ||||
| 
 | ||||
| class SelectDeviceByImeiRespModelElement { | ||||
|   int id; | ||||
|   String imei; | ||||
|   int logInType; | ||||
|   int patientId; | ||||
|   bool outSa; | ||||
|   String mobile; | ||||
|   String identificationNo; | ||||
|   String name; | ||||
|   String nameN; | ||||
|   String createdOn; | ||||
|   String editedOn; | ||||
|   bool biometricEnabled; | ||||
|   int patientType; | ||||
|   int preferredLanguage; | ||||
| 
 | ||||
|   SelectDeviceByImeiRespModelElement({ | ||||
|     required this.id, | ||||
|     required this.imei, | ||||
|     required this.logInType, | ||||
|     required this.patientId, | ||||
|     required this.outSa, | ||||
|     required this.mobile, | ||||
|     required this.identificationNo, | ||||
|     required this.name, | ||||
|     required this.nameN, | ||||
|     required this.createdOn, | ||||
|     required this.editedOn, | ||||
|     required this.biometricEnabled, | ||||
|     required this.patientType, | ||||
|     required this.preferredLanguage, | ||||
|   }); | ||||
| 
 | ||||
|   factory SelectDeviceByImeiRespModelElement.fromJson(Map<String, dynamic> json) => SelectDeviceByImeiRespModelElement( | ||||
|     id: json["ID"], | ||||
|     imei: json["IMEI"], | ||||
|     logInType: json["LogInType"], | ||||
|     patientId: json["PatientID"], | ||||
|     outSa: json["OutSA"], | ||||
|     mobile: json["Mobile"], | ||||
|     identificationNo: json["IdentificationNo"], | ||||
|     name: json["Name"], | ||||
|     nameN: json["NameN"], | ||||
|     createdOn: json["CreatedOn"], | ||||
|     editedOn: json["EditedOn"], | ||||
|     biometricEnabled: json["BiometricEnabled"], | ||||
|     patientType: json["PatientType"], | ||||
|     preferredLanguage: json["PreferredLanguage"], | ||||
|   ); | ||||
| 
 | ||||
|   Map<String, dynamic> toJson() => { | ||||
|     "ID": id, | ||||
|     "IMEI": imei, | ||||
|     "LogInType": logInType, | ||||
|     "PatientID": patientId, | ||||
|     "OutSA": outSa, | ||||
|     "Mobile": mobile, | ||||
|     "IdentificationNo": identificationNo, | ||||
|     "Name": name, | ||||
|     "NameN": nameN, | ||||
|     "CreatedOn": createdOn, | ||||
|     "EditedOn": editedOn, | ||||
|     "BiometricEnabled": biometricEnabled, | ||||
|     "PatientType": patientType, | ||||
|     "PreferredLanguage": preferredLanguage, | ||||
|   }; | ||||
| } | ||||
| @ -0,0 +1,56 @@ | ||||
| import 'package:dartz/dartz.dart'; | ||||
| import 'package:hmg_patient_app_new/core/api/api_client.dart'; | ||||
| 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/services/logger_service.dart'; | ||||
| 
 | ||||
| abstract class BookAppointmentsRepo { | ||||
|   Future<Either<Failure, dynamic>> getDoctors(); | ||||
| } | ||||
| 
 | ||||
| class BookAppointmentsRepoImp implements BookAppointmentsRepo { | ||||
|   final ApiClient apiClient; | ||||
|   final LoggerService loggerService; | ||||
| 
 | ||||
|   BookAppointmentsRepoImp({required this.loggerService, required this.apiClient}); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Either<Failure, dynamic>> getDoctors() async { | ||||
|     try { | ||||
|       // Mock API call with delayed response | ||||
|       final result = await Future.delayed( | ||||
|         const Duration(seconds: 2), | ||||
|         () => { | ||||
|           'success': true, | ||||
|           'data': [ | ||||
|             { | ||||
|               'id': '1', | ||||
|               'name': 'Dr. Ahmed Hassan', | ||||
|               'specialty': 'Cardiology', | ||||
|               'experience': '10 years', | ||||
|               'rating': 4.8, | ||||
|               'image': 'https://example.com/doctor1.jpg' | ||||
|             }, | ||||
|           ] | ||||
|         } | ||||
|       ); | ||||
| 
 | ||||
|       if (result != null && result is Map && result['success'] != null && result['success'] != false) { | ||||
|         return Right(result); | ||||
|       } else { | ||||
|         loggerService.errorLogs(result.toString()); | ||||
|         return Left(ServerFailure(result.toString())); | ||||
|       } | ||||
|     } on APIException catch (e) { | ||||
|       APIError? apiError; | ||||
|       if (e.error is APIError) { | ||||
|         apiError = e.error as APIError; | ||||
|       } | ||||
|       loggerService.errorLogs(e.toString()); | ||||
|       return Left(ServerFailure(apiError?.errorMessage ?? e.message)); | ||||
|     } catch (e) { | ||||
|       loggerService.errorLogs(e.toString()); | ||||
|       return Left(ServerFailure(e.toString())); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,13 @@ | ||||
| import 'package:hmg_patient_app_new/services/logger_service.dart'; | ||||
| 
 | ||||
| abstract class CommonRepo { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| class CommonRepoImp implements CommonRepo { | ||||
|   LoggerService loggerService; | ||||
| 
 | ||||
|   CommonRepoImp({required this.loggerService}); | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,78 @@ | ||||
| import 'package:dartz/dartz.dart'; | ||||
| import 'package:hmg_patient_app_new/core/api/api_client.dart'; | ||||
| 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/services/logger_service.dart'; | ||||
| 
 | ||||
| abstract class MyAppointmentsRepo { | ||||
|   Future<Either<Failure, dynamic>> getMyAppointments(); | ||||
| } | ||||
| 
 | ||||
| class MyAppointmentsRepoImp implements MyAppointmentsRepo { | ||||
|   final ApiClient apiClient; | ||||
|   final LoggerService loggerService; | ||||
| 
 | ||||
|   MyAppointmentsRepoImp({required this.loggerService, required this.apiClient}); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Either<Failure, dynamic>> getMyAppointments() async { | ||||
|     try { | ||||
|       // Mock API call with delayed response | ||||
|       final result = await Future.delayed( | ||||
|           const Duration(seconds: 2), | ||||
|               () => { | ||||
|             'success': true, | ||||
|             'data': [ | ||||
|               { | ||||
|                 'id': '1', | ||||
|                 'doctorName': 'Dr. Ahmed Hassan', | ||||
|                 'specialty': 'Cardiology', | ||||
|                 'appointmentDate': '2025-09-05', | ||||
|                 'appointmentTime': '10:00 AM', | ||||
|                 'status': 'confirmed', | ||||
|                 'clinicName': 'HMG Hospital', | ||||
|                 'patientName': 'John Doe' | ||||
|               }, | ||||
|               { | ||||
|                 'id': '2', | ||||
|                 'doctorName': 'Dr. Sarah Johnson', | ||||
|                 'specialty': 'Dermatology', | ||||
|                 'appointmentDate': '2025-09-08', | ||||
|                 'appointmentTime': '2:30 PM', | ||||
|                 'status': 'pending', | ||||
|                 'clinicName': 'HMG Medical Center', | ||||
|                 'patientName': 'John Doe' | ||||
|               }, | ||||
|               { | ||||
|                 'id': '3', | ||||
|                 'doctorName': 'Dr. Mohamed Ali', | ||||
|                 'specialty': 'Pediatrics', | ||||
|                 'appointmentDate': '2025-08-25', | ||||
|                 'appointmentTime': '11:15 AM', | ||||
|                 'status': 'completed', | ||||
|                 'clinicName': 'HMG Children\'s Clinic', | ||||
|                 'patientName': 'John Doe' | ||||
|               } | ||||
|             ] | ||||
|           } | ||||
|       ); | ||||
| 
 | ||||
|       if (result != null && result is Map && result['success'] != null && result['success'] != false) { | ||||
|         return Right(result); | ||||
|       } else { | ||||
|         loggerService.errorLogs(result.toString()); | ||||
|         return Left(ServerFailure(result.toString())); | ||||
|       } | ||||
|     } on APIException catch (e) { | ||||
|       APIError? apiError; | ||||
|       if (e.error is APIError) { | ||||
|         apiError = e.error as APIError; | ||||
|       } | ||||
|       loggerService.errorLogs(e.toString()); | ||||
|       return Left(ServerFailure(apiError?.errorMessage ?? e.message)); | ||||
|     } catch (e) { | ||||
|       loggerService.errorLogs(e.toString()); | ||||
|       return Left(ServerFailure(e.toString())); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -1,5 +0,0 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| 
 | ||||
| class AuthenticationViewModel extends ChangeNotifier { | ||||
|   // Add properties and methods related to authentication here | ||||
| } | ||||
| @ -1,30 +0,0 @@ | ||||
| import 'dart:convert'; | ||||
| 
 | ||||
| import 'package:hmg_patient_app_new/core/app_state.dart'; | ||||
| import 'package:http/http.dart'; | ||||
| 
 | ||||
| import '../../core/consts.dart'; | ||||
| import '../api_client.dart'; | ||||
| import 'models/response_models/get_patient_last_login_details_response_model.dart'; | ||||
| 
 | ||||
| class AuthenticationApiClient { | ||||
|   static final AuthenticationApiClient _instance = AuthenticationApiClient._internal(); | ||||
| 
 | ||||
|   AuthenticationApiClient._internal(); | ||||
| 
 | ||||
|   factory AuthenticationApiClient() => _instance; | ||||
| 
 | ||||
|   Future<GetPatientLastLoginDetailsResponseModel> getMultipleLoginUserData(String deviceIMEI) async { | ||||
|     GetPatientLastLoginDetailsResponseModel getPatientLastLoginDetailsResponseModel; | ||||
| 
 | ||||
|     Map<String, dynamic> request = {"IMEI": deviceIMEI}; | ||||
|     request.addAll(AppState().postParamsJson); | ||||
|     String url = ApiConsts.baseUrl + ApiConsts.SELECT_DEVICE_IMEI; | ||||
|     Response response = await ApiClient().postJsonForResponse(url, request); | ||||
| 
 | ||||
|     var json = jsonDecode(response.body); | ||||
|     getPatientLastLoginDetailsResponseModel = GetPatientLastLoginDetailsResponseModel.fromJson(json); | ||||
| 
 | ||||
|     return getPatientLastLoginDetailsResponseModel; | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,14 @@ | ||||
| 
 | ||||
| import 'package:shared_preferences/shared_preferences.dart'; | ||||
| 
 | ||||
| abstract class CacheService { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| class CacheServiceImp implements CacheService { | ||||
|   SharedPreferences sharedPreferences; | ||||
| 
 | ||||
|   CacheServiceImp({required this.sharedPreferences}); | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,27 @@ | ||||
| 
 | ||||
| import 'package:logger/logger.dart'; | ||||
| 
 | ||||
| abstract class LoggerService { | ||||
| 
 | ||||
|   void errorLogs(String message); | ||||
| 
 | ||||
|   void logInfo(String message); | ||||
| } | ||||
| 
 | ||||
| class LoggerServiceImp implements LoggerService { | ||||
|   Logger logger; | ||||
| 
 | ||||
|   LoggerServiceImp({required this.logger}); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|   @override | ||||
|   void errorLogs(String message) { | ||||
|     logger.e(message); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   void logInfo(String message) { | ||||
|     logger.i(message); | ||||
|   } | ||||
| } | ||||
					Loading…
					
					
				
		Reference in New Issue