diff --git a/android/agconnect-services.json b/android/agconnect-services.json
deleted file mode 100644
index 91aad2c..0000000
--- a/android/agconnect-services.json
+++ /dev/null
@@ -1,74 +0,0 @@
-{
- "agcgw":{
- "backurl":"connect-drcn.hispace.hicloud.com",
- "url":"connect-drcn.dbankcloud.cn",
- "websocketbackurl":"connect-ws-drcn.hispace.dbankcloud.com",
- "websocketurl":"connect-ws-drcn.hispace.dbankcloud.cn"
- },
- "agcgw_all":{
- "CN":"connect-drcn.dbankcloud.cn",
- "CN_back":"connect-drcn.hispace.hicloud.com",
- "DE":"connect-dre.dbankcloud.cn",
- "DE_back":"connect-dre.hispace.hicloud.com",
- "RU":"connect-drru.dbankcloud.cn",
- "RU_back":"connect-drru.hispace.hicloud.com",
- "SG":"connect-dra.dbankcloud.cn",
- "SG_back":"connect-dra.hispace.hicloud.com"
- },
- "client":{
- "cp_id":"2640966000002322881",
- "product_id":"736430079244816567",
- "client_id":"563735388191982656",
- "client_secret":"650C7C799812AFFD53A10C7756CF05FB9F215A7E49032ABA8EBF3E14B77535CF",
- "project_id":"736430079244816567",
- "app_id":"102857389",
- "api_key":"CgB6e3x9DJzMgRCmnT6dyUEkp6UsIfddb6l3w0ZEXzeiRMHEFi3400Z5fJ5qaHneU0OrAI/JRpk+DMGVs3QpUxlI",
- "package_name":"com.ejada.hmg"
- },
- "oauth_client":{
- "client_id":"102857389",
- "client_type":1
- },
- "app_info":{
- "app_id":"102857389",
- "package_name":"com.ejada.hmg"
- },
- "service":{
- "analytics":{
- "collector_url":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn",
- "collector_url_ru":"datacollector-drru.dt.hicloud.com,datacollector-drru.dt.dbankcloud.cn",
- "collector_url_sg":"datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn",
- "collector_url_de":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
- "collector_url_cn":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn",
- "resource_id":"p1",
- "channel_id":""
- },
- "search":{
- "url":"https://search-drcn.cloud.huawei.com"
- },
- "cloudstorage":{
- "storage_url":"https://agc-storage-drcn.platform.dbankcloud.cn"
- },
- "ml":{
- "mlservice_url":"ml-api-drcn.ai.dbankcloud.com,ml-api-drcn.ai.dbankcloud.cn"
- }
- },
- "region":"CN",
- "configuration_version":"3.0",
- "appInfos":[
- {
- "package_name":"com.ejada.hmg",
- "client":{
- "app_id":"102857389"
- },
- "app_info":{
- "package_name":"com.ejada.hmg",
- "app_id":"102857389"
- },
- "oauth_client":{
- "client_type":1,
- "client_id":"102857389"
- }
- }
- ]
-}
diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts
index 35dbe1b..2987d3b 100644
--- a/android/app/build.gradle.kts
+++ b/android/app/build.gradle.kts
@@ -26,8 +26,8 @@ android {
applicationId = "com.ejada.hmg"
// minSdk = 24
minSdk = 26
- targetSdk = 35
- compileSdk = 35
+ targetSdk = 36
+ compileSdk = 36
// targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
diff --git a/lib/presentation/appointments/widgets/appointment_queueing_screen.dart b/android/app/keystores/keystore
similarity index 100%
rename from lib/presentation/appointments/widgets/appointment_queueing_screen.dart
rename to android/app/keystores/keystore
diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro
index ab7b2ca..9c1827a 100644
--- a/android/app/proguard-rules.pro
+++ b/android/app/proguard-rules.pro
@@ -69,4 +69,7 @@
# Penguin classes
-keep class com.peng.pennavmap.models.** { *; }
--keep class com.peng.pennavmap.db.** { *; }
\ No newline at end of file
+-keep class com.peng.pennavmap.db.** { *; }
+
+-keep class com.hiennv.flutter_callkit_incoming.** { *; }
+-keepattributes Signature, Annotation, InnerClasses, EnclosingMethod
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 454a83c..8c1388b 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -30,9 +30,6 @@
-
@@ -98,6 +95,12 @@
+
+
+
+
+
+
@@ -122,6 +125,7 @@
-
Push Notification Background
@pragma('vm:entry-point')
@@ -30,22 +31,89 @@ Future backgroundMessageHandler(dynamic message) async {
// showCallkitIncoming(message);
_incomingCall(message.data);
return;
- } else {}
+ }
}
callPage(String sessionID, String token) async {}
_incomingCall(Map data) async {
+ print('the value of the _incomingCall remote message is $data');
+
// LandingPage.incomingCallData = IncomingCallData.fromJson(data);
// var dataItem = await AppSharedPreferences().getObject('call_data');
// if(dataItem != null ) return; // to stop repeated attempt to invoke the call
// if (LandingPage.isOpenCallPage == false) {
// LandingPage.isOpenCallPage = true;
+
+ String roomID = data['session_id'] ?? '';
+
+ // GetIt.instance().saveString(key: CacheConst.zoomRoomID, value: roomID);
+ // GetIt.instance().saveBool(key: CacheConst.isAppOpenedFromCall, value: true);
+
+ Utils.saveStringFromPrefs(CacheConst.zoomRoomID, roomID);
+ Utils.saveBoolFromPrefs(CacheConst.isAppOpenedFromCall, true);
+
WidgetsFlutterBinding.ensureInitialized();
- // var _currentUuid = Uuid().v4();
- // await FlutterCallkitIncoming.showCallkitIncoming(callKitParams);
- // }
- // LandingPage.isOpenCallPage = false;
+
+ var _currentUuid = Uuid().v4();
+ CallKitParams callKitParams = CallKitParams(
+ id: _currentUuid,
+ nameCaller: "Dr Al Habib",
+ appName: 'Dr Al Habib',
+ avatar: 'https://play-lh.googleusercontent.com/FBNNpxb7m6eM6wtW7MV1Ffp6OXOGLI38q47zcvP29OCYA1yhYH5mZzl5itZi0TgOyZpG',
+ // handle: LandingPage.incomingCallData.name,
+ type: 1,
+ textAccept: 'Accept',
+ textDecline: 'Decline',
+ missedCallNotification: NotificationParams(
+ showNotification: true,
+ isShowCallback: false,
+ subtitle: 'Missed call',
+ callbackText: '',
+ ),
+ callingNotification: const NotificationParams(
+ showNotification: false,
+ isShowCallback: true,
+ subtitle: 'Calling...',
+ callbackText: 'Hang Up',
+ ),
+ duration: 30000,
+ extra: {'userId': '1a2b3c4d'},
+ headers: {'apiKey': 'Abc@123!', 'platform': 'flutter'},
+ android: const AndroidParams(
+ isImportant: true,
+ isShowFullLockedScreen: true,
+ isCustomNotification: true,
+ isShowLogo: false,
+ logoUrl: "https://play-lh.googleusercontent.com/FBNNpxb7m6eM6wtW7MV1Ffp6OXOGLI38q47zcvP29OCYA1yhYH5mZzl5itZi0TgOyZpG",
+ ringtonePath: 'system_ringtone_default',
+ backgroundColor: '#ED1C2B',
+ backgroundUrl: 'https://saudipedia.com/en/saudipediaen/uploads/images/2024/08/02/97358.jpg',
+ actionColor: '#4CAF50',
+ textColor: '#000000',
+ incomingCallNotificationChannelName: "Incoming Call",
+ missedCallNotificationChannelName: "Missed Call",
+ isShowCallID: false),
+ ios: IOSParams(
+ iconName: 'Meena Health',
+ handleType: 'generic',
+ supportsVideo: true,
+ maximumCallGroups: 2,
+ maximumCallsPerCallGroup: 1,
+ audioSessionMode: 'default',
+ audioSessionActive: true,
+ audioSessionPreferredSampleRate: 44100.0,
+ audioSessionPreferredIOBufferDuration: 0.005,
+ supportsDTMF: true,
+ supportsHolding: true,
+ supportsGrouping: false,
+ supportsUngrouping: false,
+ ringtonePath: 'system_ringtone_default',
+ ),
+ );
+ FlutterCallkitIncoming.unsilenceEvents();
+ await FlutterCallkitIncoming.showCallkitIncoming(callKitParams);
+
await Future.delayed(Duration(milliseconds: 500));
}
@@ -224,7 +292,9 @@ class PushNotificationHandler {
print('🎈 example: onDidAcceptIncomingCall $uuid - $callerId');
await voIPKit.acceptIncomingCall(callerState: CallStateType.calling);
await voIPKit.callConnected();
- await Future.delayed(Duration(seconds: 1));
+ await Future.delayed(Duration(seconds: 2)).then((val) async {
+ await voIPKit.endCall();
+ });
// Navigator.pushNamed(
// locator().navigatorKey.currentContext!,
@@ -232,8 +302,6 @@ class PushNotificationHandler {
// arguments: CallArguments("hoover-dam", "123", "Patient", "40", "1", false),
// );
- await voIPKit.endCall();
-
// Navigator.pushNamed(navigatorKey.currentContext!, VIDEO_CALL_SCREEN,
// arguments: VideoArgus(
// reservationId: int.parse(callerId), token: null, isVideo: true));
@@ -250,7 +318,7 @@ class PushNotificationHandler {
if (fcmToken != null) onToken(fcmToken);
// }
} catch (ex) {
- print("Notification Exception: " + ex.toString());
+ print("Notification Exception: $ex");
}
FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
}
@@ -258,7 +326,7 @@ class PushNotificationHandler {
if (Platform.isIOS) {
final permission = await FirebaseMessaging.instance.requestPermission();
await FirebaseMessaging.instance.getAPNSToken().then((value) async {
- log("APNS token: " + value.toString());
+ log("APNS token: $value");
await Utils.saveStringFromPrefs(CacheConst.apnsToken, value.toString());
});
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
@@ -305,14 +373,14 @@ class PushNotificationHandler {
});
FirebaseMessaging.instance.getToken().then((String? token) {
- print("Push Notification getToken: " + token!);
+ print("Push Notification getToken: ${token!}");
onToken(token!);
}).catchError((err) {
print(err);
});
FirebaseMessaging.instance.onTokenRefresh.listen((fcm_token) {
- print("Push Notification onTokenRefresh: " + fcm_token);
+ print("Push Notification onTokenRefresh: $fcm_token");
onToken(fcm_token);
});
@@ -328,7 +396,7 @@ class PushNotificationHandler {
}
newMessage(RemoteMessage remoteMessage) async {
- print("Remote Message: " + remoteMessage.data.toString());
+ print("Remote Message: ${remoteMessage.data}");
if (remoteMessage.data.isEmpty) {
return;
}
@@ -354,7 +422,7 @@ class PushNotificationHandler {
}
onToken(String token) async {
- print("Push Notification Token: " + token);
+ print("Push Notification Token: $token");
await Utils.saveStringFromPrefs(CacheConst.pushToken, token);
}
@@ -368,9 +436,7 @@ class PushNotificationHandler {
Future requestPermissions() async {
try {
if (Platform.isIOS) {
- await flutterLocalNotificationsPlugin
- .resolvePlatformSpecificImplementation()
- ?.requestPermissions(alert: true, badge: true, sound: true);
+ await FirebaseMessaging.instance.requestPermission(alert: true, badge: true, sound: true);
} else if (Platform.isAndroid) {
Map statuses = await [
Permission.notification,
diff --git a/lib/core/utils/request_utils.dart b/lib/core/utils/request_utils.dart
index a4ea936..e57039c 100644
--- a/lib/core/utils/request_utils.dart
+++ b/lib/core/utils/request_utils.dart
@@ -1,3 +1,5 @@
+import 'dart:developer';
+
import 'package:easy_localization/easy_localization.dart';
import 'package:hijri_gregorian_calendar/hijri_gregorian_calendar.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
@@ -96,6 +98,7 @@ class RequestUtils {
request.patientIdentificationID = request.nationalID = (registeredData.patientIdentificationId ?? 0);
request.dob = registeredData.dob;
request.isRegister = registeredData.isRegister;
+ log("nationIdText: ${nationIdText}");
} else {
if (fileNo) {
request.patientID = patientId ?? int.parse(nationIdText);
@@ -199,7 +202,8 @@ class RequestUtils {
return request;
}
- static dynamic getUserSignupCompletionRequest({String? fullName, String? emailAddress, GenderTypeEnum? gender, MaritalStatusTypeEnum? maritalStatus}) {
+ static dynamic getUserSignupCompletionRequest(
+ {String? fullName, String? emailAddress, GenderTypeEnum? gender, MaritalStatusTypeEnum? maritalStatus}) {
AppState appState = getIt.get();
bool isDubai = appState.getUserRegistrationPayload.patientOutSa == 1 ? true : false;
@@ -215,11 +219,19 @@ class RequestUtils {
return {
"Patientobject": {
"TempValue": true,
- "PatientIdentificationType":
- (isDubai ? appState.getUserRegistrationPayload.patientIdentificationId?.toString().substring(0, 1) : appState.getNHICUserData.idNumber!.substring(0, 1)) == "1" ? 1 : 2,
- "PatientIdentificationNo": isDubai ? appState.getUserRegistrationPayload.patientIdentificationId.toString() : appState.getNHICUserData.idNumber.toString(),
+ "PatientIdentificationType": (isDubai
+ ? appState.getUserRegistrationPayload.patientIdentificationId?.toString().substring(0, 1)
+ : appState.getNHICUserData.idNumber!.substring(0, 1)) ==
+ "1"
+ ? 1
+ : 2,
+ "PatientIdentificationNo":
+ isDubai ? appState.getUserRegistrationPayload.patientIdentificationId.toString() : appState.getNHICUserData.idNumber.toString(),
"MobileNumber": appState.getUserRegistrationPayload.patientMobileNumber ?? 0,
- "PatientOutSA": (appState.getUserRegistrationPayload.zipCode == CountryEnum.saudiArabia.countryCode || appState.getUserRegistrationPayload.zipCode == '+966') ? 0 : 1,
+ "PatientOutSA": (appState.getUserRegistrationPayload.zipCode == CountryEnum.saudiArabia.countryCode ||
+ appState.getUserRegistrationPayload.zipCode == '+966')
+ ? 0
+ : 1,
"FirstNameN": isDubai ? "..." : appState.getNHICUserData.firstNameAr,
"FirstName": isDubai ? (names.isNotEmpty ? names[0] : "...") : appState.getNHICUserData.firstNameEn,
"MiddleNameN": isDubai ? "..." : appState.getNHICUserData.secondNameAr,
@@ -233,7 +245,10 @@ class RequestUtils {
"eHealthIDField": isDubai ? null : appState.getNHICUserData.healthId,
"DateofBirthN": date,
"EmailAddress": emailAddress,
- "SourceType": (appState.getUserRegistrationPayload.zipCode == CountryEnum.saudiArabia.countryCode || appState.getUserRegistrationPayload.zipCode == '+966') ? "1" : "2",
+ "SourceType": (appState.getUserRegistrationPayload.zipCode == CountryEnum.saudiArabia.countryCode ||
+ appState.getUserRegistrationPayload.zipCode == '+966')
+ ? "1"
+ : "2",
"PreferredLanguage": appState.getLanguageCode() == "ar" ? (isDubai ? "1" : 1) : (isDubai ? "2" : 2),
"Marital": isDubai
? (maritalStatus == MaritalStatusTypeEnum.single
@@ -247,20 +262,25 @@ class RequestUtils {
? '1'
: '2'),
},
- "PatientIdentificationID": isDubai ? appState.getUserRegistrationPayload.patientIdentificationId.toString() : appState.getNHICUserData.idNumber.toString(),
+ "PatientIdentificationID":
+ isDubai ? appState.getUserRegistrationPayload.patientIdentificationId.toString() : appState.getNHICUserData.idNumber.toString(),
"PatientMobileNumber": appState.getUserRegistrationPayload.patientMobileNumber.toString()[0] == '0'
? appState.getUserRegistrationPayload.patientMobileNumber
: '0${appState.getUserRegistrationPayload.patientMobileNumber}',
"DOB": dob,
"IsHijri": appState.getUserRegistrationPayload.isHijri,
- "PatientOutSA": (appState.getUserRegistrationPayload.zipCode == CountryEnum.saudiArabia.countryCode || appState.getUserRegistrationPayload.zipCode == '+966') ? 0 : 1,
+ "PatientOutSA": (appState.getUserRegistrationPayload.zipCode == CountryEnum.saudiArabia.countryCode ||
+ appState.getUserRegistrationPayload.zipCode == '+966')
+ ? 0
+ : 1,
"isDentalAllowedBackend": appState.getUserRegistrationPayload.isDentalAllowedBackend,
"ZipCode": appState.getUserRegistrationPayload.zipCode,
if (!isDubai) "HealthId": appState.getNHICUserData.healthId,
};
}
- static Future getAddFamilyRequest({required String nationalIDorFile, required String mobileNo, required String countryCode}) async {
+ static Future getAddFamilyRequest(
+ {required String nationalIDorFile, required String mobileNo, required String countryCode}) async {
FamilyFileRequest request = FamilyFileRequest();
int? loginType = 0;
diff --git a/lib/core/utils/size_config.dart b/lib/core/utils/size_config.dart
index 9f9d835..0f8766a 100644
--- a/lib/core/utils/size_config.dart
+++ b/lib/core/utils/size_config.dart
@@ -1,6 +1,5 @@
import 'package:flutter/cupertino.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
-import 'package:hmg_patient_app_new/core/cache_consts.dart';
class SizeConfig {
static double _blockWidth = 0;
diff --git a/lib/core/utils/size_utils.dart b/lib/core/utils/size_utils.dart
index fdd0d30..4fdc09c 100644
--- a/lib/core/utils/size_utils.dart
+++ b/lib/core/utils/size_utils.dart
@@ -1,4 +1,5 @@
import 'dart:developer';
+import 'dart:math' as math;
import 'package:flutter/material.dart'; // These are the Viewport values of your Figma Design.
@@ -6,6 +7,16 @@ import 'package:flutter/material.dart'; // These are the Viewport values of your
const num figmaDesignWidth = 375; // iPhone X / 12 base width
const num figmaDesignHeight = 812; // iPhone X / 12 base height
+
+extension ConstrainedResponsive on num {
+ /// Width with max cap for tablets
+ double get wCapped => isTablet ? math.min( w, this * 1.3) : w;
+
+ /// Height with max cap for tablets
+ double get hCapped => isTablet ? math.min(h, this * 1.3) : h;
+}
+
+
extension ResponsiveExtension on num {
double get _screenWidth => SizeUtils.width;
@@ -27,7 +38,7 @@ extension ResponsiveExtension on num {
double clamp;
if (SizeUtils.deviceType == DeviceType.tablet || _isFoldable) {
// More conservative scaling for tablets and foldables
- clamp = (aspectRatio > 1.5 || aspectRatio < 0.67) ? 1.4 : 1.1;
+ clamp = (aspectRatio > 1.5 || aspectRatio < 0.67) ? 1.6 : 1.4;
} else {
// Original logic for phones
clamp = (aspectRatio > 1.3 || aspectRatio < 0.77) ? 1.6 : 1.2;
@@ -68,7 +79,7 @@ extension ResponsiveExtension on num {
double get r {
double baseScale = (this * _screenWidth) / figmaDesignWidth;
- if (_isFoldable) {
+ if (_isFoldable || isTablet) {
// Use the same logic as enhanced width for foldables
double scale = _screenWidth / figmaDesignWidth;
scale = scale.clamp(0.8, 1.4);
diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart
index a11f285..03ff6b5 100644
--- a/lib/core/utils/utils.dart
+++ b/lib/core/utils/utils.dart
@@ -29,6 +29,7 @@ import 'package:hmg_patient_app_new/widgets/loading_dialog.dart';
import 'package:lottie/lottie.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
+import 'package:url_launcher/url_launcher.dart';
class Utils {
static AppState appState = getIt.get();
@@ -146,8 +147,9 @@ class Utils {
? getMonthArabic(dateTime.month) + " " + dateTime.day.toString() + ", " + dateTime.year.toString()
: getMonth(dateTime.month) + " " + dateTime.day.toString() + ", " + dateTime.year.toString();
}
+
static String getDayMonthYearDateFormatted(DateTime? dateTime) {
- if(dateTime == null ) return "";
+ if (dateTime == null) return "";
return appState.isArabic()
? "${dateTime.day.toString()} ${getMonthArabic(dateTime.month)}, ${dateTime.year.toString()}"
: "${dateTime.day.toString()} ${getMonth(dateTime.month)}, ${dateTime.year.toString()}";
@@ -367,10 +369,11 @@ class Utils {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height: isSmallWidget ? 0.h : 48.h),
- Lottie.asset(AppAnimations.noData, repeat: false, reverse: false, frameRate: FrameRate(60), width: width.h, height: height.h, fit: BoxFit.fill),
+ Lottie.asset(AppAnimations.noData,
+ repeat: false, reverse: false, frameRate: FrameRate(60), width: width.w, height: height.h, fit: BoxFit.fill),
SizedBox(height: 16.h),
(noDataText ?? LocaleKeys.noDataAvailable.tr())
- .toText16(weight: FontWeight.w500, color: AppColors.greyTextColor, isCenter: true)
+ .toText14(weight: FontWeight.w500, color: AppColors.greyTextColor, isCenter: true)
.paddingSymmetrical(64.w, 0.h),
SizedBox(height: 16.h),
callToActionButton
@@ -383,7 +386,8 @@ class Utils {
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Lottie.asset(AppAnimations.loadingAnimation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
+ Lottie.asset(AppAnimations.loadingAnimation,
+ repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
SizedBox(height: 8.h),
(loadingText ?? LocaleKeys.loadingText.tr()).toText16(color: AppColors.blackColor, isCenter: true),
SizedBox(height: 8.h),
@@ -391,10 +395,10 @@ class Utils {
).center;
}
- static Widget getSuccessWidget({String? loadingText}) {
+ static Widget getSuccessWidget({String? loadingText, CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center}) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
- crossAxisAlignment: CrossAxisAlignment.center,
+ crossAxisAlignment: crossAxisAlignment,
children: [
Lottie.asset(AppAnimations.checkmark, repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
SizedBox(height: 8.h),
@@ -409,7 +413,8 @@ class Utils {
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Lottie.asset(AppAnimations.errorAnimation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
+ Lottie.asset(AppAnimations.errorAnimation,
+ repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
SizedBox(height: 8.h),
(loadingText ?? LocaleKeys.loadingText.tr()).toText16(color: AppColors.blackColor),
SizedBox(height: 8.h),
@@ -417,14 +422,21 @@ class Utils {
).center;
}
- static Widget getWarningWidget({String? loadingText, bool isShowActionButtons = false, Widget? bodyWidget, Function? onConfirmTap, Function? onCancelTap}) {
+ static Widget getWarningWidget({
+ String? loadingText,
+ bool isShowActionButtons = false,
+ Widget? bodyWidget,
+ Function? onConfirmTap,
+ Function? onCancelTap,
+ }) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
- Lottie.asset(AppAnimations.warningAnimation, repeat: false, reverse: false, frameRate: FrameRate(60), width: 128.h, height: 128.h, fit: BoxFit.fill),
+ Lottie.asset(AppAnimations.warningAnimation,
+ repeat: false, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
SizedBox(height: 8.h),
- (loadingText ?? LocaleKeys.loadingText.tr()).toText14(color: AppColors.blackColor, letterSpacing: 0),
+ (loadingText ?? LocaleKeys.loadingText.tr()).toText15(color: AppColors.blackColor, letterSpacing: 0),
SizedBox(height: 16.h),
bodyWidget ?? SizedBox.shrink(),
SizedBox(height: 16.h),
@@ -742,7 +754,7 @@ class Utils {
fit: fit,
errorBuilder: errorBuilder ??
(_, __, ___) {
- //todo change the error builder icon that it is returning
+ //todo_section change the error builder icon that it is returning
return Utils.buildSvgWithAssets(width: iconW, height: iconH, icon: AppAssets.no_visit_icon);
},
);
@@ -754,10 +766,19 @@ class Utils {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Image.asset(AppAssets.mada, width: 25.h, height: 25.h),
- Image.asset(AppAssets.tamara_en, width: 25.h, height: 25.h),
+ Image.asset(
+ AppAssets.tamaraEng,
+ width: 25.h,
+ height: 25.h,
+ fit: BoxFit.contain,
+ errorBuilder: (context, error, stackTrace) {
+ debugPrint('Failed to load Tamara PNG in payment methods: $error');
+ return Utils.buildSvgWithAssets(icon: AppAssets.tamara, width: 25.h, height: 25.h, fit: BoxFit.contain);
+ },
+ ),
Image.asset(AppAssets.visa, width: 25.h, height: 25.h),
- Image.asset(AppAssets.Mastercard, width: 25.h, height: 25.h),
- Image.asset(AppAssets.apple_pay, width: 25.h, height: 25.h),
+ Image.asset(AppAssets.mastercard, width: 25.h, height: 25.h),
+ Image.asset(AppAssets.applePay, width: 25.h, height: 25.h),
],
);
}
@@ -792,14 +813,15 @@ class Utils {
);
}
- static Widget getPaymentAmountWithSymbol2(num habibWalletAmount,
- {double iconSize = 14,
+ static Widget getPaymentAmountWithSymbol2(
+ num habibWalletAmount, {
+ double iconSize = 14,
double? fontSize,
double? letterSpacing,
FontWeight? fontWeight,
Color iconColor = AppColors.textColor,
- Color textColor = AppColors.blackColor,
- bool isSaudiCurrency = true,
+ Color textColor = AppColors.blackColor,
+ bool isSaudiCurrency = true,
bool isExpanded = true,
}) {
return RichText(
@@ -816,7 +838,7 @@ class Utils {
style: TextStyle(
color: textColor,
fontSize: fontSize ?? 32.f,
- letterSpacing: letterSpacing??-4,
+ letterSpacing: letterSpacing ?? -4,
fontWeight: fontWeight ?? FontWeight.w600,
height: 1),
),
@@ -837,7 +859,11 @@ class Utils {
static Future checkConnection({bool bypassConnectionCheck = false}) async {
if (bypassConnectionCheck) return true;
List connectivityResult = await (Connectivity().checkConnectivity());
- if (connectivityResult.contains(ConnectivityResult.mobile) || connectivityResult.contains(ConnectivityResult.wifi)) {
+ if (connectivityResult.contains(ConnectivityResult.mobile) ||
+ connectivityResult.contains(ConnectivityResult.wifi) ||
+ connectivityResult.contains(ConnectivityResult.ethernet) ||
+ connectivityResult.contains(ConnectivityResult.bluetooth) ||
+ connectivityResult.contains(ConnectivityResult.vpn)) {
return true;
} else {
return false;
@@ -860,11 +886,43 @@ class Utils {
static Future createFileFromString(String encodedStr, String ext) async {
Uint8List bytes = base64.decode(encodedStr);
String dir = (await getApplicationDocumentsDirectory()).path;
- File file = File("$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext);
+ File file = File("$dir/${DateTime.now().millisecondsSinceEpoch}.$ext");
await file.writeAsBytes(bytes);
return file.path;
}
+ ///method to be used to get the text as per the langauge of the application
+ static String getTextWRTCurrentLanguage(String? englishText, String? arabicText) {
+ String? text = appState.isArabic() ? arabicText : englishText;
+ return text ?? '';
+ }
+
+ static String formatNumberToInternationalFormat(num number, {String? currencySymbol, int decimalDigit = 0}) {
+ return NumberFormat.currency(locale: 'en_US', symbol: currencySymbol ?? "", decimalDigits: decimalDigit).format(number);
+ }
+
+ static PatientDoctorAppointmentList? convertToPatientDoctorAppointmentList(HospitalsModel? hospital) {
+ if (hospital == null) return null;
+ return PatientDoctorAppointmentList(
+ filterName: hospital.name,
+ distanceInKMs: hospital.distanceInKilometers?.toString(),
+ projectTopName: hospital.name,
+ projectBottomName: hospital.name,
+ model: hospital,
+ isHMC: hospital.isHMC);
+ }
+
+
+ static HospitalsModel? convertToHospitalsModel(PatientDoctorAppointmentList? item) {
+ if (item == null) return null;
+ return HospitalsModel(
+ name: item.filterName,
+ nameN: item.filterName,
+ distanceInKilometers: item.distanceInKMs,
+ isHMC: item.isHMC,
+ );
+ }
+
static bool havePrivilege(int id) {
bool isHavePrivilege = false;
try {
@@ -877,33 +935,64 @@ class Utils {
return isHavePrivilege;
}
- ///method to be used to get the text as per the langauge of the application
- static String getTextWRTCurrentLanguage(
- String? englishText, String? arabicText) {
- String? text = appState.isArabic() ? arabicText : englishText;
- return text ?? '';
+ static void openWebView({required String url}) {
+ Uri uri = Uri.parse(url);
+ launchUrl(uri, mode: LaunchMode.inAppBrowserView);
}
+ static Color getCardBorderColor(int currentQueueStatus) {
+ switch (currentQueueStatus) {
+ case 0:
+ return AppColors.ratingColorYellow;
+ case 1:
+ return AppColors.primaryRedColor;
+ case 2:
+ return AppColors.successColor;
+ }
+ return AppColors.textColor;
+ }
- static String formatNumberToInternationalFormat(num number, {String? currencySymbol, int decimalDigit = 0}){
- return NumberFormat.currency(
- locale: 'en_US',
- symbol: currencySymbol??"",
- decimalDigits: decimalDigit)
- .format(number);
+ static Color getCardButtonColor(int currentQueueStatus) {
+ switch (currentQueueStatus) {
+ case 0:
+ return AppColors.textColor.withValues(alpha: 0.08);
+ case 1:
+ return AppColors.primaryRedColor;
+ case 2:
+ return AppColors.successColor;
+ }
+ return AppColors.primaryRedColor;
}
+ static Color getCardButtonTextColor(int currentQueueStatus) {
+ switch (currentQueueStatus) {
+ case 0:
+ return Color(0xFFA2A2A2);
+ case 1:
+ return AppColors.whiteColor;
+ case 2:
+ return AppColors.whiteColor;
+ }
+ return AppColors.primaryRedColor;
+ }
- static PatientDoctorAppointmentList? convertToPatientDoctorAppointmentList(
- HospitalsModel? hospital) {
- if (hospital == null) return null;
- return PatientDoctorAppointmentList(
- filterName: hospital.name,
- distanceInKMs: hospital.distanceInKilometers?.toString(),
- projectTopName: hospital.name,
- projectBottomName: hospital.name,
- model: hospital,
- isHMC: hospital.isHMC);
+ static String getCardButtonText(int currentQueueStatus, String roomNumber) {
+ switch (currentQueueStatus) {
+ case 0:
+ return "Please wait! you will be called for vital signs".needTranslation;
+ case 1:
+ return "Please visit Room $roomNumber for vital signs".needTranslation;
+ case 2:
+ return "Please visit Room $roomNumber to the Doctor".needTranslation;
+ }
+ return "";
}
+ static bool isDateToday(DateTime dateToCheck) {
+ final DateTime now = DateTime.now();
+ final DateTime today = DateTime(now.year, now.month, now.day);
+ final DateTime checkDate = DateTime(dateToCheck.year, dateToCheck.month, dateToCheck.day);
+
+ return checkDate == today;
+ }
}
diff --git a/lib/core/utils/validation_utils.dart b/lib/core/utils/validation_utils.dart
index 7e38300..abba447 100644
--- a/lib/core/utils/validation_utils.dart
+++ b/lib/core/utils/validation_utils.dart
@@ -101,8 +101,7 @@ class ValidationUtils {
return regex.hasMatch(id);
}
- static bool validateUaeRegistration(
- {String? name, GenderTypeEnum? gender, NationalityCountries? country, MaritalStatusTypeEnum? maritalStatus, required Function() onOkPress}) {
+ static bool validateUaeRegistration({String? name, GenderTypeEnum? gender, NationalityCountries? country, MaritalStatusTypeEnum? maritalStatus, required Function() onOkPress}) {
if (name == null || name.isEmpty) {
_dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseEnterAValidName.tr(), onOkPressed: onOkPress);
return false;
@@ -141,8 +140,7 @@ class ValidationUtils {
return true;
}
- static bool isValidatedIdAndPhoneWithCountryValidation(
- {String? nationalId, String? phoneNumber, required Function() onOkPress, CountryEnum? selectedCountry}) {
+ static bool isValidatedIdAndPhoneWithCountryValidation({String? nationalId, String? phoneNumber, required Function() onOkPress, CountryEnum? selectedCountry}) {
bool isCorrectID = true;
if (nationalId == null || nationalId.isEmpty) {
_dialogService.showExceptionBottomSheet(message: LocaleKeys.pleaseEnterAnationalID.tr(), onOkPressed: onOkPress);
@@ -171,4 +169,10 @@ class ValidationUtils {
}
return isCorrectID;
}
-}
+
+ static bool isNullOrEmpty(String? value) {
+ return value == null || value
+ .trim()
+ .isEmpty;
+ }
+}
\ No newline at end of file
diff --git a/lib/core/utils/zoom_config.dart b/lib/core/utils/zoom_config.dart
new file mode 100644
index 0000000..09370c0
--- /dev/null
+++ b/lib/core/utils/zoom_config.dart
@@ -0,0 +1,4 @@
+const Map configs = {
+ 'ZOOM_SDK_KEY': 'b9T74nhfTg-ioP9urm970A',
+ 'ZOOM_SDK_SECRET': 'KOzmjBNXQ1f4IPHpnngfL29uZvJMufSy2Fk8',
+};
diff --git a/lib/extensions/int_extensions.dart b/lib/extensions/int_extensions.dart
index 80b3171..75460c5 100644
--- a/lib/extensions/int_extensions.dart
+++ b/lib/extensions/int_extensions.dart
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
-import 'package:hmg_patient_app_new/theme/colors.dart';
extension IntExtensions on int {
Widget get height => SizedBox(height: toDouble());
diff --git a/lib/extensions/route_extensions.dart b/lib/extensions/route_extensions.dart
index 0dcc54b..b76acfa 100644
--- a/lib/extensions/route_extensions.dart
+++ b/lib/extensions/route_extensions.dart
@@ -17,7 +17,7 @@ extension NavigationExtensions on BuildContext {
Navigator.of(this).pop();
}
- void navigateTo(Widget page) {
+ void pushNavigateTo(Widget page) {
Navigator.push(this, MaterialPageRoute(builder: (context) => page));
}
diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart
index 1a6d1cc..309dde1 100644
--- a/lib/extensions/string_extensions.dart
+++ b/lib/extensions/string_extensions.dart
@@ -23,14 +23,15 @@ extension CapExtension on String {
extension EmailValidator on String {
Widget get toWidget => Text(this);
- Widget toText8({Color? color, bool isBold = false, int? maxlines, FontStyle? fontStyle, TextOverflow? textOverflow}) => Text(
+ Widget toText8({Color? color, FontWeight? fontWeight, bool isBold = false, int? maxlines, FontStyle? fontStyle, TextOverflow? textOverflow}) =>
+ Text(
this,
maxLines: maxlines,
overflow: textOverflow,
style: TextStyle(
fontSize: 8.f,
fontStyle: fontStyle ?? FontStyle.normal,
- fontWeight: isBold ? FontWeight.bold : FontWeight.normal,
+ fontWeight: fontWeight ?? (isBold ? FontWeight.bold : FontWeight.normal),
color: color ?? AppColors.blackColor,
letterSpacing: 0,
),
@@ -41,12 +42,14 @@ extension EmailValidator on String {
FontWeight? weight,
bool isBold = false,
bool isUnderLine = false,
+ bool isCenter = false,
int? maxlines,
FontStyle? fontStyle,
TextOverflow? textOverflow,
double letterSpacing = 0}) =>
Text(
this,
+ textAlign: isCenter ? TextAlign.center : null,
maxLines: maxlines,
overflow: textOverflow,
style: TextStyle(
@@ -189,7 +192,8 @@ extension EmailValidator on String {
letterSpacing: letterSpacing,
height: height,
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
- decoration: isUnderLine ? TextDecoration.underline : null),
+ decoration: isUnderLine ? TextDecoration.underline : null,
+ decorationColor: color ?? AppColors.blackColor),
);
Widget toText15(
@@ -212,37 +216,38 @@ extension EmailValidator on String {
decoration: isUnderLine ? TextDecoration.underline : null),
);
- Widget toText16({
- Color? color,
- bool isUnderLine = false,
- bool isBold = false,
- bool isCenter = false,
- int? maxlines,
- double? height,
- TextAlign? textAlign,
- FontWeight? weight,
- TextOverflow? textOverflow,
- double? letterSpacing = -0.4,
- }) =>
+ Widget toText16(
+ {Color? color,
+ bool isUnderLine = false,
+ bool isBold = false,
+ bool isCenter = false,
+ int? maxlines,
+ double? height,
+ TextAlign? textAlign,
+ FontWeight? weight,
+ TextOverflow? textOverflow,
+ double? letterSpacing = -0.4,
+ Color decorationColor = AppColors.errorColor}) =>
Text(
this,
maxLines: maxlines,
textAlign: isCenter ? TextAlign.center : null,
style: TextStyle(
- color: color ?? AppColors.blackColor,
- fontSize: 16.f,
- letterSpacing: letterSpacing,
- height: height,
- overflow: textOverflow,
- fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
- decoration: isUnderLine ? TextDecoration.underline : null,
- ),
+ color: color ?? AppColors.blackColor,
+ fontSize: 16.f,
+ letterSpacing: letterSpacing,
+ height: height,
+ overflow: textOverflow,
+ fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
+ decoration: isUnderLine ? TextDecoration.underline : null,
+ decorationColor: decorationColor),
);
Widget toText17({Color? color, bool isBold = false, bool isCenter = false}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
- style: TextStyle(color: color ?? AppColors.blackColor, fontSize: 17.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
+ style: TextStyle(
+ color: color ?? AppColors.blackColor, fontSize: 17.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
);
Widget toText18({Color? color, FontWeight? weight, bool isBold = false, bool isCenter = false, int? maxlines, TextOverflow? textOverflow}) => Text(
@@ -251,39 +256,62 @@ extension EmailValidator on String {
this,
overflow: textOverflow,
style: TextStyle(
- fontSize: 18.f, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), color: color ?? AppColors.blackColor, letterSpacing: -0.4),
+ fontSize: 18.f,
+ fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
+ color: color ?? AppColors.blackColor,
+ letterSpacing: -0.4),
);
Widget toText19({Color? color, bool isBold = false}) => Text(
this,
- style: TextStyle(fontSize: 19.f, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, color: color ?? AppColors.blackColor, letterSpacing: -0.4),
+ style: TextStyle(
+ fontSize: 19.f, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, color: color ?? AppColors.blackColor, letterSpacing: -0.4),
);
- Widget toText20({Color? color, FontWeight? weight, bool isBold = false}) => Text(
+ Widget toText20({
+ Color? color,
+ FontWeight? weight,
+ bool isBold = false,
+ }) =>
+ Text(
this,
style: TextStyle(
- fontSize: 20.f, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), color: color ?? AppColors.blackColor, letterSpacing: -0.4),
+ fontSize: 20.f,
+ fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal),
+ color: color ?? AppColors.blackColor,
+ letterSpacing: -0.4),
);
Widget toText21({Color? color, bool isBold = false, FontWeight? weight, int? maxlines}) => Text(
this,
maxLines: maxlines,
style: TextStyle(
- color: color ?? AppColors.blackColor, fontSize: 21.f, letterSpacing: -1, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal)),
+ color: color ?? AppColors.blackColor,
+ fontSize: 21.f,
+ letterSpacing: -1,
+ fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal)),
);
Widget toText22({Color? color, bool isBold = false, bool isCenter = false}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
style: TextStyle(
- height: 1, color: color ?? AppColors.blackColor, fontSize: 22.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
+ height: 1,
+ color: color ?? AppColors.blackColor,
+ fontSize: 22.f,
+ letterSpacing: -1,
+ fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
);
Widget toText24({Color? color, bool isBold = false, bool isCenter = false, FontWeight? fontWeight, double? letterSpacing}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
style: TextStyle(
- height: 23 / 24, color: color ?? AppColors.blackColor, fontSize: 24.f, letterSpacing: letterSpacing??-1, fontWeight: isBold ? FontWeight.bold : fontWeight??FontWeight.normal),
+ height: 23 / 24,
+ color: color ?? AppColors.blackColor,
+ fontSize: 24.f,
+ letterSpacing: letterSpacing ?? -1,
+ fontWeight: isBold ? FontWeight.bold : fontWeight ?? FontWeight.normal),
);
Widget toText26({Color? color, bool isBold = false, double? height, bool isCenter = false, FontWeight? weight, double? letterSpacing}) => Text(
@@ -297,28 +325,36 @@ extension EmailValidator on String {
fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal)),
);
- Widget toText28({Color? color, bool isBold = false, double? height, bool isCenter = false}) => Text(
+ Widget toText28({Color? color, bool isBold = false, double? height, bool isCenter = false, double? letterSpacing}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
style: TextStyle(
height: height ?? 23 / 28,
color: color ?? AppColors.blackColor,
fontSize: 28.f,
- letterSpacing: -1,
+ letterSpacing: letterSpacing ?? -1,
fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
);
- Widget toText32({Color? color, bool isBold = false, bool isCenter = false}) => Text(
+ Widget toText32({FontWeight? weight, Color? color, bool isBold = false, bool isCenter = false}) => Text(
this,
textAlign: isCenter ? TextAlign.center : null,
style: TextStyle(
- height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 32.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
+ height: 32 / 32,
+ color: color ?? AppColors.blackColor,
+ fontSize: 32.f,
+ letterSpacing: -1,
+ fontWeight: isBold ? FontWeight.bold : weight ?? FontWeight.normal),
);
Widget toText44({Color? color, bool isBold = false}) => Text(
this,
style: TextStyle(
- height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 44.f, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
+ height: 32 / 32,
+ color: color ?? AppColors.blackColor,
+ fontSize: 44.f,
+ letterSpacing: -1,
+ fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
);
Widget toSectionHeading({String upperHeading = "", String lowerHeading = ""}) {
diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart
index 424aa88..70f10bb 100644
--- a/lib/extensions/widget_extensions.dart
+++ b/lib/extensions/widget_extensions.dart
@@ -1,9 +1,8 @@
-import 'package:hmg_patient_app_new/core/enums.dart';
-import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:flutter/material.dart';
-import 'package:flutter/widgets.dart';
+import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/extensions/int_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
+import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:shimmer/shimmer.dart';
import 'package:sizer/sizer.dart';
import 'package:smooth_corner/smooth_corner.dart';
@@ -19,7 +18,8 @@ extension WidgetExtensions on Widget {
Widget paddingAll(double _value) => Padding(padding: EdgeInsets.all(_value), child: this);
- Widget paddingSymmetrical(double horizontal, double vertical) => Padding(padding: EdgeInsets.symmetric(horizontal: horizontal, vertical: vertical), child: this);
+ Widget paddingSymmetrical(double horizontal, double vertical) =>
+ Padding(padding: EdgeInsets.symmetric(horizontal: horizontal, vertical: vertical), child: this);
Widget paddingOnly({double left = 0.0, double right = 0.0, double top = 0.0, double bottom = 0.0}) =>
Padding(padding: EdgeInsetsDirectional.only(start: left, end: right, top: top, bottom: bottom), child: this);
@@ -99,7 +99,7 @@ extension WidgetExtensions on Widget {
bool disablePadding = false,
double radius = 20,
Color? color,
- Color borderColor = AppColors.buttonColor,
+ Color? borderColor,
bool disableWidth = false,
bool isAlignment = false}) {
return Container(
@@ -110,7 +110,7 @@ extension WidgetExtensions on Widget {
),
color: color,
border: Border.all(
- color: borderColor,
+ color: borderColor ?? Colors.transparent,
width: disableWidth ? 2 : 1,
),
),
diff --git a/lib/features/authentication/authentication_repo.dart b/lib/features/authentication/authentication_repo.dart
index d566996..9b09c43 100644
--- a/lib/features/authentication/authentication_repo.dart
+++ b/lib/features/authentication/authentication_repo.dart
@@ -5,10 +5,8 @@ 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/app_state.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
-import 'package:hmg_patient_app_new/core/common_models/privilege/PrivilegeModel.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
-import 'package:hmg_patient_app_new/features/authentication/models/request_models/check_activation_code_register_request_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';
@@ -101,10 +99,7 @@ class AuthenticationRepoImp implements AuthenticationRepo {
}
@override
- Future>> checkPatientAuthentication({
- required dynamic checkPatientAuthenticationReq,
- String? languageID,
- }) async {
+ Future>> checkPatientAuthentication({required dynamic checkPatientAuthenticationReq, String? languageID}) async {
int isOutKsa = (checkPatientAuthenticationReq.zipCode == '966' || checkPatientAuthenticationReq.zipCode == '+966') ? 0 : 1;
checkPatientAuthenticationReq.patientOutSA = isOutKsa;
try {
@@ -149,7 +144,6 @@ class AuthenticationRepoImp implements AuthenticationRepo {
sendActivationCodeReq.isDentalAllowedBackend = false;
final payload = sendActivationCodeReq.toJson();
if (isFormFamilyFile) {
-
payload.remove("MobileNo");
payload.remove("NationalID");
payload.remove("SMSSignature");
@@ -265,6 +259,12 @@ class AuthenticationRepoImp implements AuthenticationRepo {
newRequest.isDentalAllowedBackend = false;
newRequest.forRegisteration = newRequest.isRegister ?? false;
newRequest.isRegister = false;
+ //silent login case removed token and login token
+ if(newRequest.logInTokenID.isEmpty && newRequest.isSilentLogin == true && (newRequest.loginType==1 || newRequest.loginType==4)) {
+ newRequest.logInTokenID = null;
+ newRequest.deviceToken = null;
+ }
+
}
Map familyRequest = {};
diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart
index bcdacac..b393772 100644
--- a/lib/features/authentication/authentication_view_model.dart
+++ b/lib/features/authentication/authentication_view_model.dart
@@ -27,12 +27,12 @@ import 'package:hmg_patient_app_new/features/authentication/models/resp_models/a
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/check_user_staus_nhic_response_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart';
-import 'package:hmg_patient_app_new/features/medical_file/medical_file_repo.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_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/authentication/saved_login_screen.dart';
+import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
import 'package:hmg_patient_app_new/routes/app_routes.dart';
import 'package:hmg_patient_app_new/services/cache_service.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
@@ -40,6 +40,7 @@ import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/localauth_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
+import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:sms_otp_auto_verify/sms_otp_auto_verify.dart';
import 'models/request_models/get_user_mobile_device_data.dart';
@@ -339,7 +340,7 @@ class AuthenticationViewModel extends ChangeNotifier {
_navigationService.pop();
});
},
- activationCode: null, //todo silent login case halded on the repo itself..
+ activationCode: null, //todo_section silent login case halded on the repo itself..
);
}
}
@@ -566,7 +567,7 @@ class AuthenticationViewModel extends ChangeNotifier {
if (!_appState.getIsChildLoggedIn) {
await medicalVm.getFamilyFiles(status: 0);
await medicalVm.getAllPendingRecordsByResponseId();
- _navigationService.popUntilNamed(AppRoutes.landingScreen);
+ _navigationService.replaceAllRoutesAndNavigateToLanding();
}
} else {
if (activation.list != null && activation.list!.isNotEmpty) {
@@ -586,6 +587,7 @@ class AuthenticationViewModel extends ChangeNotifier {
activation.list!.first.bloodGroup = activation.patientBlodType;
_appState.setAuthenticatedUser(activation.list!.first);
_appState.setPrivilegeModelList(activation.list!.first.listPrivilege!);
+ _appState.setUserBloodGroup = activation.patientBlodType ?? "N/A";
}
// _appState.setUserBloodGroup = (activation.patientBlodType ?? "");
_appState.setAppAuthToken = activation.authenticationTokenId;
@@ -675,7 +677,12 @@ class AuthenticationViewModel extends ChangeNotifier {
}
Future navigateToHomeScreen() async {
- _navigationService.pushAndReplace(AppRoutes.landingScreen);
+ Navigator.pushAndRemoveUntil(
+ _navigationService.navigatorKey.currentContext!,
+ CustomPageRoute(
+ page: LandingNavigation(),
+ ),
+ (r) => false);
}
Future navigateToOTPScreen(
@@ -852,16 +859,13 @@ class AuthenticationViewModel extends ChangeNotifier {
request['isRegister'] = true;
_appState.setAppAuthToken = response['LogInTokenID'];
if (isPatientOutsideSA(request: response)) {
- print("=======OUT SA=======");
sendActivationCode(
- otpTypeEnum: OTPTypeEnumExtension.fromInt(request["OTP_SendType"]),
- nationalIdOrFileNumber: request["PatientIdentificationID"].toString(),
- phoneNumber: request["PatientMobileNumber"].toString(),
- payload: request,
- isForRegister: true,
- );
+ otpTypeEnum: OTPTypeEnumExtension.fromInt(request["OTP_SendType"]),
+ nationalIdOrFileNumber: request["PatientIdentificationID"].toString(),
+ phoneNumber: request["PatientMobileNumber"].toString(),
+ payload: request,
+ isForRegister: true);
} else {
- print("=======IN SA=======");
chekUserNHICData(request: request);
}
}
diff --git a/lib/features/blood_donation/blood_donation_repo.dart b/lib/features/blood_donation/blood_donation_repo.dart
new file mode 100644
index 0000000..dce0975
--- /dev/null
+++ b/lib/features/blood_donation/blood_donation_repo.dart
@@ -0,0 +1,96 @@
+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/blood_donation/models/blood_group_response_model.dart';
+import 'package:hmg_patient_app_new/features/blood_donation/models/cities_model.dart';
+import 'package:hmg_patient_app_new/services/logger_service.dart';
+
+abstract class BloodDonationRepo {
+ Future>>> getAllCities();
+
+ Future>> getPatientBloodGroupDetails();
+}
+
+class BloodDonationRepoImp implements BloodDonationRepo {
+ final ApiClient apiClient;
+ final LoggerService loggerService;
+
+ BloodDonationRepoImp({required this.loggerService, required this.apiClient});
+
+ @override
+ Future>>> getAllCities() async {
+ Map mapDevice = {};
+
+ try {
+ GenericApiModel>? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_CITIES_REQUEST,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['ListCities'];
+ final citiesList = list.map((item) => CitiesModel.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel>(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: citiesList,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>> getPatientBloodGroupDetails() async {
+ Map mapDevice = {};
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_BLOOD_REQUEST,
+ body: mapDevice,
+ isAllowAny: true,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['List_BloodGroupDetails'][0];
+ final patientBloodGroup = List_BloodGroupDetailsModel.fromJson(list);
+
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: patientBloodGroup,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/features/blood_donation/blood_donation_view_model.dart b/lib/features/blood_donation/blood_donation_view_model.dart
new file mode 100644
index 0000000..b8f0e9c
--- /dev/null
+++ b/lib/features/blood_donation/blood_donation_view_model.dart
@@ -0,0 +1,147 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/core/app_state.dart';
+import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
+import 'package:hmg_patient_app_new/features/blood_donation/blood_donation_repo.dart';
+import 'package:hmg_patient_app_new/features/blood_donation/models/blood_group_list_model.dart';
+import 'package:hmg_patient_app_new/features/blood_donation/models/blood_group_response_model.dart';
+import 'package:hmg_patient_app_new/features/blood_donation/models/cities_model.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/error_handler_service.dart';
+import 'package:hmg_patient_app_new/services/navigation_service.dart';
+
+class BloodDonationViewModel extends ChangeNotifier {
+ final DialogService dialogService;
+ BloodDonationRepo bloodDonationRepo;
+ ErrorHandlerService errorHandlerService;
+ final NavigationService navigationService;
+ final AppState appState;
+
+ List citiesList = [];
+ List bloodGroupList = [
+ BloodGroupListModel("O+", 0),
+ BloodGroupListModel("O-", 1),
+ BloodGroupListModel("AB+", 2),
+ BloodGroupListModel("AB-", 3),
+ BloodGroupListModel("A+", 4),
+ BloodGroupListModel("A-", 5),
+ BloodGroupListModel("B+", 6),
+ BloodGroupListModel("B-", 7),
+ ];
+
+ List genderList = [
+ BloodGroupListModel(LocaleKeys.malE.tr(), 1),
+ BloodGroupListModel("Female".needTranslation.tr(), 2),
+ ];
+
+ late CitiesModel selectedCity;
+ late BloodGroupListModel selectedBloodGroup;
+ int _selectedHospitalIndex = 0;
+ int _selectedBloodTypeIndex = 0;
+ String selectedBloodType = '';
+
+ List_BloodGroupDetailsModel patientBloodGroupDetailsModel = List_BloodGroupDetailsModel();
+
+ BloodDonationViewModel({required this.bloodDonationRepo, required this.errorHandlerService, required this.navigationService, required this.dialogService, required this.appState});
+
+ setSelectedCity(CitiesModel city) {
+ selectedCity = city;
+ notifyListeners();
+ }
+
+ setSelectedBloodGroup(BloodGroupListModel bloodGroup) {
+ selectedBloodGroup = bloodGroup;
+ selectedBloodType = selectedBloodGroup.name;
+ notifyListeners();
+ }
+
+ Future getRegionSelectedClinics({Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ citiesList.clear();
+ selectedCity = CitiesModel();
+ notifyListeners();
+ final result = await bloodDonationRepo.getAllCities();
+
+ result.fold(
+ (failure) async {
+ onError!(failure.message);
+ },
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ onError!(apiResponse.errorMessage ?? 'An unexpected error occurred');
+ } else if (apiResponse.messageStatus == 1) {
+ citiesList = apiResponse.data!;
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+
+ Future getPatientBloodGroupDetails({Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ final result = await bloodDonationRepo.getPatientBloodGroupDetails();
+
+ result.fold(
+ (failure) async {
+ onError!(failure.message);
+ },
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ onError!(apiResponse.errorMessage ?? 'An unexpected error occurred');
+ } else if (apiResponse.messageStatus == 1) {
+ patientBloodGroupDetailsModel = apiResponse.data!;
+
+ CitiesModel citiesModel = CitiesModel();
+ citiesModel.iD = getSelectedCityID();
+ _selectedHospitalIndex = (citiesModel.iD! - 1);
+ citiesModel.description = citiesList[_selectedHospitalIndex].description;
+ citiesModel.descriptionN = citiesList[_selectedHospitalIndex].descriptionN;
+ selectedCity = citiesModel;
+ selectedBloodType = patientBloodGroupDetailsModel.bloodGroup!;
+ _selectedBloodTypeIndex = getBloodIndex(selectedBloodType);
+
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+
+ int getSelectedCityID() {
+ int cityID = 1;
+ citiesList.forEach((element) {
+ if (element.description == patientBloodGroupDetailsModel.city) {
+ cityID = element.iD!;
+ }
+ });
+ return cityID;
+ }
+
+ int getBloodIndex(String type) {
+ switch (type) {
+ case "O+":
+ return 0;
+ case "O-":
+ return 1;
+ case "AB+":
+ return 2;
+ case "AB-":
+ return 3;
+ case "A+":
+ return 4;
+ case "A-":
+ return 5;
+ case "B+":
+ return 6;
+ case "B-":
+ return 7;
+
+ default:
+ return 0;
+ }
+ }
+}
diff --git a/lib/features/blood_donation/models/blood_group_list_model.dart b/lib/features/blood_donation/models/blood_group_list_model.dart
new file mode 100644
index 0000000..9a98cc5
--- /dev/null
+++ b/lib/features/blood_donation/models/blood_group_list_model.dart
@@ -0,0 +1,6 @@
+class BloodGroupListModel {
+ String name;
+ int value;
+
+ BloodGroupListModel(this.name, this.value);
+}
diff --git a/lib/features/blood_donation/models/blood_group_response_model.dart b/lib/features/blood_donation/models/blood_group_response_model.dart
new file mode 100644
index 0000000..ceaca78
--- /dev/null
+++ b/lib/features/blood_donation/models/blood_group_response_model.dart
@@ -0,0 +1,61 @@
+class List_BloodGroupDetailsModel {
+ int? iD;
+ int? patientID;
+ int? patientType;
+ bool? patientOutSA;
+ int? zipCode;
+ String? cellNumber;
+ String? cityCode;
+ String? city;
+ int? gender;
+ String? bloodGroup;
+ String? nationalID;
+ bool? isActive;
+
+ List_BloodGroupDetailsModel({
+ this.iD,
+ this.patientID,
+ this.patientType,
+ this.patientOutSA,
+ this.zipCode,
+ this.cellNumber,
+ this.cityCode,
+ this.city,
+ this.gender,
+ this.bloodGroup,
+ this.nationalID,
+ this.isActive,
+ });
+
+ List_BloodGroupDetailsModel.fromJson(Map json) {
+ iD = json['ID'];
+ patientID = json['PatientID'];
+ patientType = json['PatientType'];
+ patientOutSA = json['PatientOutSA'];
+ zipCode = json['ZipCode'];
+ cellNumber = json['CellNumber'];
+ cityCode = json['CityCode'];
+ city = json['City'];
+ gender = json['Gender'];
+ bloodGroup = json['BloodGroup'];
+ nationalID = json['NationalID'];
+ isActive = json['IsActive'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['ID'] = this.iD;
+ data['PatientID'] = this.patientID;
+ data['PatientType'] = this.patientType;
+ data['PatientOutSA'] = this.patientOutSA;
+ data['ZipCode'] = this.zipCode;
+ data['CellNumber'] = this.cellNumber;
+ data['CityCode'] = this.cityCode;
+ data['City'] = this.city;
+ data['Gender'] = this.gender;
+ data['BloodGroup'] = this.bloodGroup;
+ data['NationalID'] = this.nationalID;
+ data['IsActive'] = this.isActive;
+ return data;
+ }
+}
diff --git a/lib/features/blood_donation/models/cities_model.dart b/lib/features/blood_donation/models/cities_model.dart
new file mode 100644
index 0000000..cf7e631
--- /dev/null
+++ b/lib/features/blood_donation/models/cities_model.dart
@@ -0,0 +1,21 @@
+class CitiesModel {
+ int? iD;
+ String? description;
+ String? descriptionN;
+
+ CitiesModel({this.iD, this.description, this.descriptionN});
+
+ CitiesModel.fromJson(Map json) {
+ iD = json['ID'];
+ description = json['Description'];
+ descriptionN = json['DescriptionN'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['ID'] = this.iD;
+ data['Description'] = this.description;
+ data['DescriptionN'] = this.descriptionN;
+ return data;
+ }
+}
\ No newline at end of file
diff --git a/lib/features/book_appointments/book_appointments_repo.dart b/lib/features/book_appointments/book_appointments_repo.dart
index 8aafc9b..cfd473e 100644
--- a/lib/features/book_appointments/book_appointments_repo.dart
+++ b/lib/features/book_appointments/book_appointments_repo.dart
@@ -1,4 +1,3 @@
-import 'dart:io';
import 'package:dartz/dartz.dart';
import 'package:hmg_patient_app_new/core/api/api_client.dart';
@@ -6,6 +5,7 @@ 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/core/utils/date_util.dart';
+import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/appointment_nearest_gate_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/dental_chief_complaints_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctor_profile_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctors_list_response_model.dart';
@@ -14,6 +14,7 @@ import 'package:hmg_patient_app_new/features/book_appointments/models/resp_model
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_patient_dental_plan_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_share_response_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
import 'models/resp_models/laser_body_parts.dart';
@@ -25,9 +26,12 @@ abstract class BookAppointmentsRepo {
Future>>> getDoctorsList(int clinicID, int projectID, bool isNearest, int doctorId, String doctorName, {isContinueDentalPlan = false});
+ Future>>> getDoctorsListByHealthCal(int calculationID);
+
Future>> getDoctorProfile(int clinicID, int projectID, int doctorId, {Function(dynamic)? onSuccess, Function(String)? onError});
- Future>> getDoctorFreeSlots(int clinicID, int projectID, int doctorId, bool isBookingForLiveCare, {bool continueDentalPlan = false, Function(dynamic)? onSuccess, Function(String)? onError});
+ Future>> getDoctorFreeSlots(int clinicID, int projectID, int doctorId, bool isBookingForLiveCare,
+ {bool continueDentalPlan = false, Function(dynamic)? onSuccess, Function(String)? onError});
Future>> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel});
@@ -82,8 +86,25 @@ abstract class BookAppointmentsRepo {
Future>>> getDentalChiefComplaintDoctorsList(int projectID, int chiefComplaintID,
{Function(dynamic)? onSuccess, Function(String)? onError});
- Future>>> getLaserClinics(int laserCategoryID, int projectID, int languageID,
- {Function(dynamic)? onSuccess, Function(String)? onError});
+ Future>>> getLaserClinics(int laserCategoryID, int projectID, int languageID, {Function(dynamic)? onSuccess, Function(String)? onError});
+
+ Future>> checkScannedNFCAndQRCode(String nfcCode, int projectId, {Function(dynamic)? onSuccess, Function(String)? onError});
+
+ Future>> getPatientShareWalkInAppointment({required int projectID, required int clinicID, required int doctorID});
+
+ Future>> insertSpecificAppointmentForWalkIn(
+ {required int docID,
+ required int clinicID,
+ required int projectID,
+ required String selectedTime,
+ required String selectedDate,
+ required int initialSlotDuration,
+ required int genderID,
+ required int userAge,
+ Function(dynamic)? onSuccess,
+ Function(String)? onError});
+
+ Future>> getAppointmentNearestGate({required int projectID, required int clinicID});
}
class BookAppointmentsRepoImp implements BookAppointmentsRepo {
@@ -189,6 +210,45 @@ class BookAppointmentsRepoImp implements BookAppointmentsRepo {
}
}
+ @override
+ Future>>> getDoctorsListByHealthCal(int calculationID, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ Map mapDevice = {"CalculationID": calculationID};
+
+ try {
+ GenericApiModel>? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_DOCTOR_LIST_CALCULATION,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ onError!(error);
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['List_CalculationTable'];
+
+ final doctorsList = list.map((item) => DoctorsListResponseModel.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel>(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: doctorsList,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
@override
Future>> getDoctorProfile(int clinicID, int projectID, int doctorId, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
Map mapDevice = {
@@ -807,7 +867,8 @@ class BookAppointmentsRepoImp implements BookAppointmentsRepo {
}
@override
- Future>>> getLaserClinics(int laserCategoryID, int projectID, int languageID, {Function(dynamic p1)? onSuccess, Function(String p1)? onError}) async {
+ Future>>> getLaserClinics(int laserCategoryID, int projectID, int languageID,
+ {Function(dynamic p1)? onSuccess, Function(String p1)? onError}) async {
Map mapDevice = {
"LaserCategoryID": laserCategoryID,
"ProjectID": projectID,
@@ -848,4 +909,180 @@ class BookAppointmentsRepoImp implements BookAppointmentsRepo {
return Left(UnknownFailure(e.toString()));
}
}
+
+ @override
+ Future> checkScannedNFCAndQRCode(String nfcCode, int projectId, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ Map mapDevice = {"NFC_Code": nfcCode, "ProjectID": projectId};
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ CHECK_SCANNED_NFC_QR_CODE,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: response,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>> getPatientShareWalkInAppointment({required int projectID, required int clinicID, required int doctorID}) async {
+ Map mapRequest = {"ProjectID": projectID, "ClinicID": clinicID, "DoctorID": doctorID};
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_PATIENT_SHARE_FOR_WALKIN_APPOINTMENT,
+ body: mapRequest,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['OnlineCheckInAppointmentsWalkInModel'];
+ if (list == null || list.isEmpty) {
+ throw Exception("patient share list is empty");
+ }
+
+ final patientShareObj = PatientAppointmentShareResponseModel.fromJson(list);
+ patientShareObj.isCash = response["IsCash"];
+ patientShareObj.isEligible = response["IsEligible"];
+ patientShareObj.isInsured = response["IsInsured"];
+
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: patientShareObj,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future> insertSpecificAppointmentForWalkIn(
+ {required int docID,
+ required int clinicID,
+ required int projectID,
+ required String selectedTime,
+ required String selectedDate,
+ required int initialSlotDuration,
+ required int genderID,
+ required int userAge,
+ Function(dynamic)? onSuccess,
+ Function(String)? onError}) async {
+ Map mapDevice = {
+ "IsForLiveCare": true,
+ "ProjectID": projectID,
+ "ClinicID": clinicID,
+ "DoctorID": docID,
+ "StartTime": selectedTime,
+ "SelectedTime": selectedTime,
+ "EndTime": selectedTime,
+ "InitialSlotDuration": initialSlotDuration,
+ "StrAppointmentDate": selectedDate,
+ "IsVirtual": false,
+ "BookedBy": 102,
+ "VisitType": 1,
+ "VisitFor": 1,
+ "GenderID": genderID,
+ "Age": userAge
+ };
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ INSERT_WALKIN_APPOINTMENT,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final appointmentNo = response['AppointmentNo'];
+
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: response["ErrorEndUserMessage"],
+ data: response,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>> getAppointmentNearestGate({required int projectID, required int clinicID}) async {
+ Map mapRequest = {"ProjectID": projectID, "ClinicID": clinicID};
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_APPOINTMENT_NEAREST_GATE,
+ body: mapRequest,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final nearestGateResponse = AppointmentNearestGateResponseModel.fromJson(response['getGateByProjectIDandClinicIDList'][0]);
+
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: nearestGateResponse,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
}
diff --git a/lib/features/book_appointments/book_appointments_view_model.dart b/lib/features/book_appointments/book_appointments_view_model.dart
index f24766b..cbed940 100644
--- a/lib/features/book_appointments/book_appointments_view_model.dart
+++ b/lib/features/book_appointments/book_appointments_view_model.dart
@@ -3,7 +3,6 @@ import 'dart:async';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.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/dependencies.dart';
import 'package:hmg_patient_app_new/core/location_util.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
@@ -15,6 +14,7 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_repo.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/LaserCategoryType.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/free_slot.dart';
+import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/appointment_nearest_gate_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/dental_chief_complaints_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctor_profile_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctors_list_response_model.dart';
@@ -25,6 +25,7 @@ import 'package:hmg_patient_app_new/features/book_appointments/models/timeslots.
import 'package:hmg_patient_app_new/features/my_appointments/models/facility_selection.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_share_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/home/navigation_screen.dart';
@@ -44,11 +45,17 @@ class BookAppointmentsViewModel extends ChangeNotifier {
bool isDoctorsListLoading = false;
bool isDoctorProfileLoading = false;
bool isDoctorSearchByNameStarted = false;
+ bool isAppointmentNearestGateLoading = false;
bool isLiveCareSchedule = false;
+ bool isGetDocForHealthCal = false;
+ int? calculationID = 0;
+ bool isSortByClinic = true;
int initialSlotDuration = 0;
+ bool isNearestAppointmentSelected = false;
+
LocationUtils locationUtils;
List clinicsList = [];
@@ -61,6 +68,11 @@ class BookAppointmentsViewModel extends ChangeNotifier {
List doctorsList = [];
List filteredDoctorList = [];
+ // Grouped doctors lists
+ List> doctorsListByClinic = [];
+ List> doctorsListByHospital = [];
+ List> doctorsListGrouped = [];
+
List liveCareDoctorsList = [];
List patientDentalPlanEstimationList = [];
@@ -105,8 +117,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
List searchedRegionList = [];
List facilityList = ["hmgHospitals", "hmcMedicalClinic"];
List searchedHospitalList = [];
- List
- searchedPatientDoctorAppointmentHospitalsList = [];
+ List searchedPatientDoctorAppointmentHospitalsList = [];
List searchedClinicList = [];
PatientDoctorAppointmentList? selectedHospitalForFilters;
@@ -114,15 +125,25 @@ class BookAppointmentsViewModel extends ChangeNotifier {
String? selectedClinicForFilters;
bool applyFilters = false;
+ bool isWaitingAppointmentAvailable = false;
+
+ bool isWaitingAppointmentSelected = false;
+ int waitingAppointmentProjectID = 0;
+ DoctorsListResponseModel? waitingAppointmentDoctor;
+ String waitingAppointmentNFCCode = "";
+
+ PatientAppointmentShareResponseModel? patientWalkInAppointmentShareResponseModel;
+
+ AppointmentNearestGateResponseModel? appointmentNearestGateResponseModel;
///variables for laser clinic
- List femaleLaserCategory = [
+ List femaleLaserCategory = [
LaserCategoryType(1, 'bodyString'),
LaserCategoryType(2, 'face'),
- LaserCategoryType(10,'bikini'),
+ LaserCategoryType(10, 'bikini'),
LaserCategoryType(11, 'retouch'),
];
- List maleLaserCategory =[
+ List maleLaserCategory = [
LaserCategoryType(1, 'body'),
LaserCategoryType(2, 'face'),
LaserCategoryType(11, 'retouch'),
@@ -137,8 +158,37 @@ class BookAppointmentsViewModel extends ChangeNotifier {
int duration = 0;
+ setIsSortByClinic(bool value) {
+ isSortByClinic = value;
+ doctorsListGrouped = isSortByClinic ? doctorsListByClinic : doctorsListByHospital;
+ notifyListeners();
+ }
+
+ // Group doctors by clinic and hospital
+ void _groupDoctorsList() {
+ final clinicMap = >{};
+ final hospitalMap = >{};
+
+ for (var doctor in doctorsList) {
+ final clinicKey = (doctor.clinicName ?? 'Unknown').trim();
+ clinicMap.putIfAbsent(clinicKey, () => []).add(doctor);
+
+ final hospitalKey = (doctor.projectName ?? 'Unknown').trim();
+ hospitalMap.putIfAbsent(hospitalKey, () => []).add(doctor);
+ }
+
+ doctorsListByClinic = clinicMap.values.toList();
+ doctorsListByHospital = hospitalMap.values.toList();
+ doctorsListGrouped = isSortByClinic ? doctorsListByClinic : doctorsListByHospital;
+ }
+
BookAppointmentsViewModel(
- {required this.bookAppointmentsRepo, required this.errorHandlerService, required this.navigationService, required this.myAppointmentsViewModel, required this.locationUtils, required this.dialogService }) {
+ {required this.bookAppointmentsRepo,
+ required this.errorHandlerService,
+ required this.navigationService,
+ required this.myAppointmentsViewModel,
+ required this.locationUtils,
+ required this.dialogService}) {
initBookAppointmentViewModel();
}
@@ -170,11 +220,44 @@ class BookAppointmentsViewModel extends ChangeNotifier {
dentalChiefComplaintsList.clear();
isContinueDentalPlan = false;
isChiefComplaintsListLoading = true;
+ isWaitingAppointmentSelected = false;
bodyTypes = [maleLaserCategory, femaleLaserCategory];
// getLocation();
notifyListeners();
}
+ setIsNearestAppointmentSelected(bool isNearestAppointmentSelected) {
+ this.isNearestAppointmentSelected = isNearestAppointmentSelected;
+
+ if (isNearestAppointmentSelected) {
+ doctorsList.sort((a, b) => DateUtil.convertStringToDate(a.nearestFreeSlot!).compareTo(DateUtil.convertStringToDate(b.nearestFreeSlot!)));
+ } else {
+ doctorsList.sort((a, b) => b.decimalDoctorRate!.compareTo(a.decimalDoctorRate!));
+ }
+
+ notifyListeners();
+ }
+
+ setIsWaitingAppointmentSelected(bool isWaitingAppointmentSelected) {
+ this.isWaitingAppointmentSelected = isWaitingAppointmentSelected;
+ notifyListeners();
+ }
+
+ setWaitingAppointmentDoctor(DoctorsListResponseModel waitingAppointmentDoctor) {
+ this.waitingAppointmentDoctor = waitingAppointmentDoctor;
+ notifyListeners();
+ }
+
+ setWaitingAppointmentNFCCode(String waitingAppointmentNFCCode) {
+ this.waitingAppointmentNFCCode = waitingAppointmentNFCCode;
+ notifyListeners();
+ }
+
+ setWaitingAppointmentProjectID(int projectID) {
+ waitingAppointmentProjectID = projectID;
+ notifyListeners();
+ }
+
setIsDoctorsListLoading(bool value) {
if (value) {
doctorsList.clear();
@@ -248,6 +331,8 @@ class BookAppointmentsViewModel extends ChangeNotifier {
}
void onTabChanged(int index) {
+ calculationID = null;
+ isGetDocForHealthCal = false;
selectedTabIndex = index;
notifyListeners();
}
@@ -333,16 +418,49 @@ class BookAppointmentsViewModel extends ChangeNotifier {
}
//TODO: Make the API dynamic with parameters for ProjectID, isNearest, languageID, doctorId, doctorName
- Future getDoctorsList({int projectID = 0, bool isNearest = false, int doctorId = 0, String doctorName = "", Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ Future getDoctorsList({int projectID = 0, bool isNearest = true, int doctorId = 0, String doctorName = "", Function(dynamic)? onSuccess, Function(String)? onError}) async {
doctorsList.clear();
projectID = currentlySelectedHospitalFromRegionFlow != null ? int.parse(currentlySelectedHospitalFromRegionFlow!) : projectID;
- final result = await bookAppointmentsRepo.getDoctorsList(selectedClinic.clinicID ?? 0, projectID, isNearest, doctorId, doctorName, isContinueDentalPlan: isContinueDentalPlan);
+ final result =
+ await bookAppointmentsRepo.getDoctorsList(selectedClinic.clinicID ?? 0, projectID, doctorName.isNotEmpty ? false : isNearest, doctorId, doctorName, isContinueDentalPlan: isContinueDentalPlan);
result.fold(
(failure) async {
isDoctorsListLoading = false;
+ if (onError != null) onError("No doctors found for the search criteria".needTranslation);
+
+ notifyListeners();
+ },
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ doctorsList = apiResponse.data!;
+ filteredDoctorList = doctorsList;
+ isDoctorsListLoading = false;
+ doctorsList.sort((a, b) => b.decimalDoctorRate!.compareTo(a.decimalDoctorRate!));
+ initializeFilteredList();
+ clearSearchFilters();
+ getFiltersFromDoctorList();
+ _groupDoctorsList();
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+
+ //TODO: GetDockets & Calculations For Health Calculator
+ Future getDoctorsListByHealthCal({Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ doctorsList.clear();
+ final result = await bookAppointmentsRepo.getDoctorsListByHealthCal(calculationID!);
+ result.fold(
+ (failure) async {
+ isDoctorsListLoading = false;
+ if (onError != null) onError("No doctors found for the search criteria".needTranslation);
- onError!("No doctors found for the search criteria".needTranslation);
notifyListeners();
},
(apiResponse) {
@@ -350,11 +468,13 @@ class BookAppointmentsViewModel extends ChangeNotifier {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
doctorsList = apiResponse.data!;
+ setIsSortByClinic(true);
filteredDoctorList = doctorsList;
isDoctorsListLoading = false;
initializeFilteredList();
clearSearchFilters();
getFiltersFromDoctorList();
+ _groupDoctorsList();
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
@@ -374,10 +494,10 @@ class BookAppointmentsViewModel extends ChangeNotifier {
final result = await bookAppointmentsRepo.getDoctorsList(selectedClinic.clinicID ?? 0, projectID, isNearest, doctorId, doctorName);
result.fold(
- (failure) async {
+ (failure) async {
onError?.call("No doctors found for the search criteria".needTranslation);
},
- (apiResponse) async {
+ (apiResponse) async {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
@@ -451,6 +571,9 @@ class BookAppointmentsViewModel extends ChangeNotifier {
}
initialSlotDuration = apiResponse.data["InitialSlotDuration"];
freeSlotsResponse = apiResponse.data['FreeTimeSlots'];
+ isWaitingAppointmentAvailable = apiResponse.data["IsAllowToBookWaitingAppointment"];
+ // isWaitingAppointmentAvailable = true;
+
freeSlotsResponse.forEach((element) {
// date = (isLiveCareSchedule != null && isLiveCareSchedule)
// ? DateUtil.convertStringToDate(element)
@@ -857,11 +980,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
}
void setSelections(
- List? selectedFacilityForFilters,
- List? selectedRegionForFilters,
- String? selectedClinicForFilters,
- PatientDoctorAppointmentList? selectedHospitalForFilters,
- bool applyFilters) {
+ List? selectedFacilityForFilters, List? selectedRegionForFilters, String? selectedClinicForFilters, PatientDoctorAppointmentList? selectedHospitalForFilters, bool applyFilters) {
this.selectedFacilityForFilters = selectedFacilityForFilters;
this.selectedClinicForFilters = selectedClinicForFilters;
this.selectedHospitalForFilters = selectedHospitalForFilters;
@@ -872,17 +991,14 @@ class BookAppointmentsViewModel extends ChangeNotifier {
void getFiltersFromDoctorList() {
doctorsList.forEach((element) {
- if (!searchedRegionList
- .contains(element.getRegionName(_appState.isArabic()))) {
- searchedRegionList
- .add(element.getRegionName(_appState.isArabic()) ?? "");
+ if (!searchedRegionList.contains(element.getRegionName(_appState.isArabic()))) {
+ searchedRegionList.add(element.getRegionName(_appState.isArabic()) ?? "");
}
if (!searchedHospitalList.contains(element.projectName)) {
- searchedPatientDoctorAppointmentHospitalsList
- .add(PatientDoctorAppointmentList()
- ..filterName = element.projectName
- ..isHMC = element.isHMC
- ..distanceInKMs = "0");
+ searchedPatientDoctorAppointmentHospitalsList.add(PatientDoctorAppointmentList()
+ ..filterName = element.projectName
+ ..isHMC = element.isHMC
+ ..distanceInKMs = "0");
searchedHospitalList.add(element.projectName ?? "");
}
if (!searchedClinicList.contains(element.clinicName)) {
@@ -932,34 +1048,18 @@ class BookAppointmentsViewModel extends ChangeNotifier {
List getDoctorListAsPerSelection() {
if (!applyFilters) return doctorsList;
- if ((selectedRegionForFilters?.isEmpty == true) &&
- (selectedFacilityForFilters?.isEmpty == true) &&
- selectedClinicForFilters == null &&
- selectedHospitalForFilters == null) {
+ if ((selectedRegionForFilters?.isEmpty == true) && (selectedFacilityForFilters?.isEmpty == true) && selectedClinicForFilters == null && selectedHospitalForFilters == null) {
return doctorsList;
}
var list = doctorsList.where((element) {
- var isInSelectedRegion = (selectedRegionForFilters?.isEmpty == true)
- ? true
- : selectedRegionForFilters
- ?.any((region) => region == element.getRegionName(isArabic()));
- var shouldApplyFacilityFilter =
- (selectedFacilityForFilters?.isEmpty == true) ? false : true;
- var isHMC = (selectedFacilityForFilters?.isEmpty == true)
- ? true
- : selectedFacilityForFilters?.any((item) => item.contains("hmc"));
- var isInSelectedClinic = (selectedClinicForFilters == null)
- ? true
- : selectedClinicForFilters == element.clinicName;
- var isInSelectedHospital = (selectedHospitalForFilters == null)
- ? true
- : element.projectName == selectedHospitalForFilters?.filterName;
+ var isInSelectedRegion = (selectedRegionForFilters?.isEmpty == true) ? true : selectedRegionForFilters?.any((region) => region == element.getRegionName(isArabic()));
+ var shouldApplyFacilityFilter = (selectedFacilityForFilters?.isEmpty == true) ? false : true;
+ var isHMC = (selectedFacilityForFilters?.isEmpty == true) ? true : selectedFacilityForFilters?.any((item) => item.contains("hmc"));
+ var isInSelectedClinic = (selectedClinicForFilters == null) ? true : selectedClinicForFilters == element.clinicName;
+ var isInSelectedHospital = (selectedHospitalForFilters == null) ? true : element.projectName == selectedHospitalForFilters?.filterName;
var facilityFilter = ((shouldApplyFacilityFilter == true) ? isHMC : true);
- return (isInSelectedRegion ?? true) &&
- (facilityFilter ?? true) &&
- isInSelectedClinic &&
- isInSelectedHospital;
+ return (isInSelectedRegion ?? true) && (facilityFilter ?? true) && isInSelectedClinic && isInSelectedHospital;
}).toList();
return list;
}
@@ -1042,6 +1142,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
// initializeFilteredList();
// clearSearchFilters();
// getFiltersFromDoctorList();
+ _groupDoctorsList();
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
@@ -1051,7 +1152,7 @@ class BookAppointmentsViewModel extends ChangeNotifier {
);
}
- setBodyType(int bodyType){
+ setBodyType(int bodyType) {
selectedBodyTypeIndex = bodyType;
selectedCategory = 0;
selectedBodyPartList = [];
@@ -1059,33 +1160,33 @@ class BookAppointmentsViewModel extends ChangeNotifier {
notifyListeners();
}
- FutureOr getLaserClinic() async{
+ FutureOr getLaserClinic() async {
isBodyPartsLoading = true;
int id = bodyTypes[selectedBodyTypeIndex][selectedCategory].laserCategoryID;
int projectID = currentlySelectedHospitalFromRegionFlow != null ? int.parse(currentlySelectedHospitalFromRegionFlow!) : 0;
int languageID = _appState.isArabic() ? 1 : 0;
final result = await bookAppointmentsRepo.getLaserClinics(id, projectID, languageID);
result.fold(
- (failure) {
+ (failure) {
isBodyPartsLoading = false;
notifyListeners();
},
- (apiResponse) {isBodyPartsLoading = false;
+ (apiResponse) {
+ isBodyPartsLoading = false;
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
- List response =apiResponse.data!;
- if(response.first.category == 2 || response.first.category == 10 ) response.remove(response.first);
+ List response = apiResponse.data!;
+ if (response.first.category == 2 || response.first.category == 10) response.remove(response.first);
laserBodyPartsList = response;
}
- notifyListeners();
-
+ notifyListeners();
},
);
}
int getDuration() {
- var duration = 0;
+ var duration = 0;
var lowerUpperLegsList = selectedBodyPartList.where((element) => element.mappingCode == "47" || element.mappingCode == "48")?.toList() ?? [];
var upperLowerArmsList = selectedBodyPartList.where((element) => element.mappingCode == "40" || element.mappingCode == "41")?.toList() ?? [];
@@ -1110,21 +1211,25 @@ class BookAppointmentsViewModel extends ChangeNotifier {
}
void setSelectedBodyPart(LaserBodyPart part) {
- if(selectedBodyPartList.contains(part)){
+ if (selectedBodyPartList.contains(part)) {
selectedBodyPartList.remove(part);
this.duration = getDuration();
notifyListeners();
} else {
- if(this.duration == 90){
- dialogService.showErrorBottomSheet(message: "Duration can not exceed 90 min".needTranslation,);
+ if (this.duration == 90) {
+ dialogService.showErrorBottomSheet(
+ message: "Duration can not exceed 90 min".needTranslation,
+ );
return;
}
selectedBodyPartList.add(part);
var duration = getDuration();
- if(duration > 90){
+ if (duration > 90) {
selectedBodyPartList.remove(part);
- dialogService.showErrorBottomSheet(message: "Duration Exceeds 90 min".needTranslation,);
+ dialogService.showErrorBottomSheet(
+ message: "Duration Exceeds 90 min".needTranslation,
+ );
return;
}
this.duration = duration;
@@ -1137,10 +1242,10 @@ class BookAppointmentsViewModel extends ChangeNotifier {
}
String getLaserProcedureNameWRTLanguage(LaserBodyPart part) {
- if(_appState.isArabic()){
- return part.bodyPartN??"";
- }else {
- return part.bodyPart??"";
+ if (_appState.isArabic()) {
+ return part.bodyPartN ?? "";
+ } else {
+ return part.bodyPart ?? "";
}
}
@@ -1151,4 +1256,123 @@ class BookAppointmentsViewModel extends ChangeNotifier {
laserBodyPartsList = [];
duration = 0;
}
+
+ Future checkScannedNFCAndQRCode(String nfcCode, int projectId, {Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ final result = await bookAppointmentsRepo.checkScannedNFCAndQRCode(nfcCode, projectId);
+
+ result.fold(
+ (failure) async {
+ onError!("Invalid verification point scanned.".needTranslation);
+ },
+ (apiResponse) {
+ // if (apiResponse.data['returnValue'] == 0) {
+ // onError!("Invalid verification point scanned.".needTranslation);
+ // } else if (apiResponse.data['returnValue'] == 1) {
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ // }
+ },
+ );
+ }
+
+ Future getWalkInPatientShareAppointment({Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ final result = await bookAppointmentsRepo.getPatientShareWalkInAppointment(projectID: waitingAppointmentProjectID, clinicID: selectedDoctor.clinicID!, doctorID: selectedDoctor.doctorID!);
+
+ result.fold(
+ (failure) async {
+ if (onError != null) {
+ onError(failure.message);
+ }
+ // await errorHandlerService.handleError(
+ // failure: failure,
+ // onOkPressed: () {
+ // onError!(failure.message);
+ // });
+ },
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ onError!(apiResponse.errorMessage!);
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ patientWalkInAppointmentShareResponseModel = apiResponse.data!;
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+
+ Future insertSpecificAppointmentForWalkIn({Function(dynamic p1)? onSuccess, Function(dynamic p1)? onError}) async {
+ _appState = getIt();
+ final result = await bookAppointmentsRepo.insertSpecificAppointmentForWalkIn(
+ docID: selectedDoctor.doctorID!,
+ clinicID: selectedDoctor.clinicID!,
+ projectID: selectedDoctor.projectID!,
+ selectedDate: selectedAppointmentDate,
+ selectedTime: selectedAppointmentTime,
+ initialSlotDuration: initialSlotDuration,
+ genderID: _appState.getAuthenticatedUser()!.gender!,
+ userAge: _appState.getAuthenticatedUser()!.age!,
+ onError: onError);
+
+ result.fold(
+ (failure) async {
+ print(failure);
+ },
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ LoadingUtils.hideFullScreenLoader();
+ showCommonBottomSheetWithoutHeight(
+ title: LocaleKeys.notice.tr(context: navigationService.navigatorKey.currentContext!),
+ navigationService.navigatorKey.currentContext!,
+ child: Utils.getErrorWidget(loadingText: apiResponse.errorMessage),
+ callBackFunc: () {},
+ isFullScreen: false,
+ isCloseButtonVisible: true,
+ );
+ } else if (apiResponse.messageStatus == 1) {
+ if (apiResponse.data == null || apiResponse.data!.isEmpty) {
+ onError!("Unexpected Error Occurred".needTranslation);
+ return;
+ }
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+
+ Future getAppointmentNearestGate({required int projectID, required int clinicID, Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ isAppointmentNearestGateLoading = true;
+ notifyListeners();
+
+ final result = await bookAppointmentsRepo.getAppointmentNearestGate(projectID: projectID, clinicID: clinicID);
+
+ result.fold(
+ (failure) async {
+ if (onError != null) {
+ onError(failure.message);
+ }
+ },
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ onError!(apiResponse.errorMessage!);
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ appointmentNearestGateResponseModel = apiResponse.data!;
+ isAppointmentNearestGateLoading = false;
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
}
diff --git a/lib/features/book_appointments/models/resp_models/appointment_nearest_gate_response_model.dart b/lib/features/book_appointments/models/resp_models/appointment_nearest_gate_response_model.dart
new file mode 100644
index 0000000..bdaa4e2
--- /dev/null
+++ b/lib/features/book_appointments/models/resp_models/appointment_nearest_gate_response_model.dart
@@ -0,0 +1,64 @@
+class AppointmentNearestGateResponseModel {
+ String? clinicDescription;
+ String? clinicDescriptionN;
+ int? clinicID;
+ String? clinicLocation;
+ String? clinicLocationN;
+ int? gender;
+ int? iD;
+ String? nearestGateNumber;
+ String? nearestGateNumberN;
+ int? projectID;
+ String? projectName;
+ String? projectNameN;
+ int? rowID;
+
+ AppointmentNearestGateResponseModel(
+ {this.clinicDescription,
+ this.clinicDescriptionN,
+ this.clinicID,
+ this.clinicLocation,
+ this.clinicLocationN,
+ this.gender,
+ this.iD,
+ this.nearestGateNumber,
+ this.nearestGateNumberN,
+ this.projectID,
+ this.projectName,
+ this.projectNameN,
+ this.rowID});
+
+ AppointmentNearestGateResponseModel.fromJson(Map json) {
+ clinicDescription = json['ClinicDescription'];
+ clinicDescriptionN = json['ClinicDescriptionN'];
+ clinicID = json['ClinicID'];
+ clinicLocation = json['ClinicLocation'];
+ clinicLocationN = json['ClinicLocationN'];
+ gender = json['Gender'];
+ iD = json['ID'];
+ nearestGateNumber = json['NearestGateNumber'];
+ nearestGateNumberN = json['NearestGateNumberN'];
+ projectID = json['ProjectID'];
+ projectName = json['ProjectName'];
+ projectNameN = json['ProjectNameN'];
+ rowID = json['RowID'];
+ }
+
+ Map toJson() {
+ final Map data = Map();
+ data['ClinicDescription'] = clinicDescription;
+ data['ClinicDescriptionN'] = clinicDescriptionN;
+ data['ClinicID'] = clinicID;
+ data['ClinicLocation'] = clinicLocation;
+ data['ClinicLocationN'] = clinicLocationN;
+ data['Gender'] = gender;
+ data['ID'] = iD;
+ data['NearestGateNumber'] = nearestGateNumber;
+ data['NearestGateNumberN'] = nearestGateNumberN;
+ data['ProjectID'] = projectID;
+ data['ProjectName'] = projectName;
+ data['ProjectNameN'] = projectNameN;
+ data['RowID'] = rowID;
+ return data;
+ }
+}
diff --git a/lib/features/book_appointments/models/resp_models/doctors_list_response_model.dart b/lib/features/book_appointments/models/resp_models/doctors_list_response_model.dart
index 5df6ed8..75ed122 100644
--- a/lib/features/book_appointments/models/resp_models/doctors_list_response_model.dart
+++ b/lib/features/book_appointments/models/resp_models/doctors_list_response_model.dart
@@ -65,75 +65,77 @@ class DoctorsListResponseModel {
String? regionID;
String? projectBottomName;
String? projectTopName;
+ int? calcID;
-
- DoctorsListResponseModel(
- {this.clinicID,
- this.clinicName,
- this.clinicNameN,
- this.doctorTitle,
- this.iD,
- this.name,
- this.projectID,
- this.projectName,
- this.actualDoctorRate,
- this.clinicRoomNo,
- this.date,
- this.dayName,
- this.decimalDoctorRate,
- this.doctorAvailability,
- this.doctorID,
- this.doctorImageURL,
- this.doctorMobileNumber,
- this.doctorProfile,
- this.doctorProfileInfo,
- this.doctorRate,
- this.doctorStarsRate,
- this.employmentType,
- this.gender,
- this.genderDescription,
- this.hISRegionId,
- this.isActive,
- this.isAllowWaitList,
- this.isAppointmentAllowed,
- this.isDoctorAllowVedioCall,
- this.isDoctorDummy,
- this.isDoctorHasPrePostImages,
- this.isHMC,
- this.isHmg,
- this.isLiveCare,
- this.latitude,
- this.longitude,
- this.nationalityFlagURL,
- this.nationalityID,
- this.nationalityName,
- this.nearestFreeSlot,
- this.noOfFreeSlotsAvailable,
- this.noOfPatientsRate,
- this.originalClinicID,
- this.personRate,
- this.projectDistanceInKiloMeters,
- this.projectNameBottom,
- this.projectNameTop,
- this.qR,
- this.qRString,
- this.rateNumber,
- this.regionName,
- this.regionNameN,
- this.serviceID,
- this.setupID,
- this.speciality,
- this.specialityN,
- this.transactionType,
- this.virtualEmploymentType,
- this.workingHours,
- this.vida3Id,
- this.region,
- this.regionArabic,
- this.regionEnglish,
- this.regionID,
- this.projectBottomName,
- this.projectTopName,});
+ DoctorsListResponseModel({
+ this.clinicID,
+ this.clinicName,
+ this.clinicNameN,
+ this.doctorTitle,
+ this.iD,
+ this.name,
+ this.projectID,
+ this.projectName,
+ this.actualDoctorRate,
+ this.clinicRoomNo,
+ this.date,
+ this.dayName,
+ this.decimalDoctorRate,
+ this.doctorAvailability,
+ this.doctorID,
+ this.doctorImageURL,
+ this.doctorMobileNumber,
+ this.doctorProfile,
+ this.doctorProfileInfo,
+ this.doctorRate,
+ this.doctorStarsRate,
+ this.employmentType,
+ this.gender,
+ this.genderDescription,
+ this.hISRegionId,
+ this.isActive,
+ this.isAllowWaitList,
+ this.isAppointmentAllowed,
+ this.isDoctorAllowVedioCall,
+ this.isDoctorDummy,
+ this.isDoctorHasPrePostImages,
+ this.isHMC,
+ this.isHmg,
+ this.isLiveCare,
+ this.latitude,
+ this.longitude,
+ this.nationalityFlagURL,
+ this.nationalityID,
+ this.nationalityName,
+ this.nearestFreeSlot,
+ this.noOfFreeSlotsAvailable,
+ this.noOfPatientsRate,
+ this.originalClinicID,
+ this.personRate,
+ this.projectDistanceInKiloMeters,
+ this.projectNameBottom,
+ this.projectNameTop,
+ this.qR,
+ this.qRString,
+ this.rateNumber,
+ this.regionName,
+ this.regionNameN,
+ this.serviceID,
+ this.setupID,
+ this.speciality,
+ this.specialityN,
+ this.transactionType,
+ this.virtualEmploymentType,
+ this.workingHours,
+ this.vida3Id,
+ this.region,
+ this.regionArabic,
+ this.regionEnglish,
+ this.regionID,
+ this.projectBottomName,
+ this.projectTopName,
+ this.calcID,
+ });
DoctorsListResponseModel.fromJson(Map json) {
clinicID = json['ClinicID'];
@@ -141,7 +143,7 @@ class DoctorsListResponseModel {
clinicNameN = json['ClinicNameN'];
doctorTitle = json['DoctorTitle'];
iD = json['ID'];
- name = json['Name'];
+ name = json['Name'] ?? json["DoctorName"];
projectID = json['ProjectID'];
projectName = json['ProjectName'];
actualDoctorRate = json['ActualDoctorRate'];
@@ -174,7 +176,7 @@ class DoctorsListResponseModel {
longitude = json['Longitude'];
nationalityFlagURL = json['NationalityFlagURL'];
nationalityID = json['NationalityID'];
- nationalityName = json['NationalityName'];
+ nationalityName = json['NationalityName'] ?? json["Nationality"];
nearestFreeSlot = json['NearestFreeSlot'];
noOfFreeSlotsAvailable = json['NoOfFreeSlotsAvailable'];
noOfPatientsRate = json['NoOfPatientsRate'];
@@ -200,6 +202,7 @@ class DoctorsListResponseModel {
regionEnglish = json['RegionName'];
projectBottomName = json['ProjectNameBottom'];
projectTopName = json['ProjectNameTop'];
+ calcID = json["CalcID"];
}
Map toJson() {
@@ -264,6 +267,7 @@ class DoctorsListResponseModel {
data['VirtualEmploymentType'] = this.virtualEmploymentType;
data['WorkingHours'] = this.workingHours;
data['vida3Id'] = this.vida3Id;
+ data['CalcID'] = this.calcID;
return data;
}
@@ -273,7 +277,8 @@ class DoctorsListResponseModel {
}
return regionEnglish;
}
- String getProjectCompleteName(){
+
+ String getProjectCompleteName() {
return "${this.projectTopName} ${this.projectBottomName}";
}
diff --git a/lib/features/book_appointments/models/resp_models/get_allergies_response_model.dart b/lib/features/book_appointments/models/resp_models/get_allergies_response_model.dart
new file mode 100644
index 0000000..cd4802f
--- /dev/null
+++ b/lib/features/book_appointments/models/resp_models/get_allergies_response_model.dart
@@ -0,0 +1,37 @@
+class GetAllergiesResponseModel {
+ int? patientID;
+ int? allergyDiseaseType;
+ int? allergyDiseaseID;
+ String? description;
+ String? descriptionN;
+ String? remarks;
+
+ GetAllergiesResponseModel({
+ this.patientID,
+ this.allergyDiseaseType,
+ this.allergyDiseaseID,
+ this.description,
+ this.descriptionN,
+ this.remarks,
+ });
+
+ GetAllergiesResponseModel.fromJson(Map json) {
+ patientID = json['PatientID'];
+ allergyDiseaseType = json['AllergyDiseaseType'];
+ allergyDiseaseID = json['AllergyDiseaseID'];
+ description = json['Description'];
+ descriptionN = json['DescriptionN'];
+ remarks = json['Remarks'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['PatientID'] = this.patientID;
+ data['AllergyDiseaseType'] = this.allergyDiseaseType;
+ data['AllergyDiseaseID'] = this.allergyDiseaseID;
+ data['Description'] = this.description;
+ data['DescriptionN'] = this.descriptionN;
+ data['Remarks'] = this.remarks;
+ return data;
+ }
+}
diff --git a/lib/features/contact_us/contact_us_repo.dart b/lib/features/contact_us/contact_us_repo.dart
new file mode 100644
index 0000000..3e96f91
--- /dev/null
+++ b/lib/features/contact_us/contact_us_repo.dart
@@ -0,0 +1,143 @@
+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/contact_us/models/req_models/request_insert_coc_item.dart';
+import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_hmg_locations.dart';
+import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_patient_ic_projects.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
+import 'package:hmg_patient_app_new/services/logger_service.dart';
+
+abstract class ContactUsRepo {
+ Future>>> getHMGLocations();
+
+ Future>>> getLiveChatProjectsList();
+
+ Future>> insertCOCItem({required RequestInsertCOCItem requestInsertCOCItem, PatientAppointmentHistoryResponseModel? patientSelectedAppointment});
+}
+
+class ContactUsRepoImp implements ContactUsRepo {
+ final ApiClient apiClient;
+ final LoggerService loggerService;
+
+ ContactUsRepoImp({required this.apiClient, required this.loggerService});
+
+ @override
+ Future>>> getHMGLocations() async {
+ Map mapDevice = {};
+
+ try {
+ GenericApiModel>? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_FINDUS_REQUEST,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['ListHMGLocation'];
+ final hmgLocations = list.map((item) => GetHMGLocationsModel.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel>(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: hmgLocations,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>>> getLiveChatProjectsList() async {
+ Map mapDevice = {};
+
+ try {
+ GenericApiModel>? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_LIVECHAT_REQUEST,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['List_PatientICProjects'];
+ final liveChatProjectsList = list.map((item) => GetPatientICProjectsModel.fromJson(item as Map)).toList().cast();
+
+ apiResponse = GenericApiModel>(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: liveChatProjectsList,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>> insertCOCItem({required RequestInsertCOCItem requestInsertCOCItem, PatientAppointmentHistoryResponseModel? patientSelectedAppointment}) async {
+ final Map body = requestInsertCOCItem.toJson();
+
+ if (patientSelectedAppointment != null) {
+ body['AppoinmentNo'] = patientSelectedAppointment.appointmentNo;
+ body['AppointmentDate'] = patientSelectedAppointment.appointmentDate;
+ body['ClinicID'] = patientSelectedAppointment.clinicID;
+ body['ClinicName'] = patientSelectedAppointment.clinicName;
+ body['DoctorID'] = patientSelectedAppointment.doctorID;
+ body['DoctorName'] = patientSelectedAppointment.doctorNameObj;
+ body['ProjectName'] = patientSelectedAppointment.projectName;
+ }
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ SEND_FEEDBACK,
+ body: body,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: response,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+}
diff --git a/lib/features/contact_us/contact_us_view_model.dart b/lib/features/contact_us/contact_us_view_model.dart
new file mode 100644
index 0000000..1185700
--- /dev/null
+++ b/lib/features/contact_us/contact_us_view_model.dart
@@ -0,0 +1,198 @@
+import 'dart:io';
+
+import 'package:flutter/material.dart';
+import 'package:hmg_patient_app_new/core/api_consts.dart';
+import 'package:hmg_patient_app_new/core/app_state.dart';
+import 'package:hmg_patient_app_new/core/utils/utils.dart';
+import 'package:hmg_patient_app_new/features/contact_us/contact_us_repo.dart';
+import 'package:hmg_patient_app_new/features/contact_us/models/feedback_type.dart';
+import 'package:hmg_patient_app_new/features/contact_us/models/req_models/request_insert_coc_item.dart';
+import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_hmg_locations.dart';
+import 'package:hmg_patient_app_new/features/contact_us/models/resp_models/get_patient_ic_projects.dart';
+import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
+import 'package:hmg_patient_app_new/services/error_handler_service.dart';
+
+class ContactUsViewModel extends ChangeNotifier {
+ ContactUsRepo contactUsRepo;
+ ErrorHandlerService errorHandlerService;
+ AppState appState;
+
+ bool isHMGLocationsListLoading = false;
+ bool isHMGHospitalsListSelected = true;
+ bool isLiveChatProjectsListLoading = false;
+ bool isSendFeedbackTabSelected = true;
+
+ List hmgHospitalsLocationsList = [];
+ List hmgPharmacyLocationsList = [];
+
+ List liveChatProjectsList = [];
+
+ int selectedLiveChatProjectIndex = -1;
+
+ List feedbackAttachmentList = [];
+
+ PatientAppointmentHistoryResponseModel? patientFeedbackSelectedAppointment;
+
+ List feedbackTypeList = [
+ FeedbackType(id: 1, nameEN: "Complaint for appointment", nameAR: 'شكوى على موعد'),
+ FeedbackType(id: 2, nameEN: "Complaint without appointment", nameAR: 'شكوى بدون موعد'),
+ FeedbackType(id: 3, nameEN: "Question", nameAR: 'سؤال'),
+ FeedbackType(id: 4, nameEN: "Appreciation", nameAR: 'تقدير'),
+ FeedbackType(id: 6, nameEN: "Suggestion", nameAR: 'إقتراح'),
+ FeedbackType(id: 5, nameEN: "Not classified", nameAR: 'غير محدد'),
+ ];
+
+ FeedbackType selectedFeedbackType = FeedbackType(id: 5, nameEN: "Not classified", nameAR: 'غير محدد');
+
+ ContactUsViewModel({required this.contactUsRepo, required this.errorHandlerService, required this.appState});
+
+ initContactUsViewModel() {
+ isHMGLocationsListLoading = true;
+ isHMGHospitalsListSelected = true;
+ isLiveChatProjectsListLoading = true;
+ hmgHospitalsLocationsList.clear();
+ hmgPharmacyLocationsList.clear();
+ liveChatProjectsList.clear();
+ feedbackAttachmentList.clear();
+ selectedFeedbackType = FeedbackType(id: 5, nameEN: "Not classified", nameAR: 'غير محدد');
+ setPatientFeedbackSelectedAppointment(null);
+ getHMGLocations();
+ notifyListeners();
+ }
+
+ setHMGHospitalsListSelected(bool isSelected) {
+ isHMGHospitalsListSelected = isSelected;
+ notifyListeners();
+ }
+
+ setSelectedLiveChatProjectIndex(int index) {
+ selectedLiveChatProjectIndex = index;
+ notifyListeners();
+ }
+
+ setIsSendFeedbackTabSelected(bool isSelected) {
+ isSendFeedbackTabSelected = isSelected;
+ notifyListeners();
+ }
+
+ setSelectedFeedbackType(FeedbackType feedbackType) {
+ selectedFeedbackType = feedbackType;
+ notifyListeners();
+ }
+
+ addFeedbackAttachment(String attachmentPath) {
+ feedbackAttachmentList.add(attachmentPath);
+ notifyListeners();
+ }
+
+ removeFeedbackAttachment(String attachmentPath) {
+ feedbackAttachmentList.remove(attachmentPath);
+ notifyListeners();
+ }
+
+ setPatientFeedbackSelectedAppointment(PatientAppointmentHistoryResponseModel? appointment) {
+ patientFeedbackSelectedAppointment = appointment;
+ notifyListeners();
+ }
+
+ Future getHMGLocations({Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ isHMGLocationsListLoading = true;
+ hmgHospitalsLocationsList.clear();
+ hmgPharmacyLocationsList.clear();
+ notifyListeners();
+
+ final result = await contactUsRepo.getHMGLocations();
+
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(failure: failure),
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ // hmgLocationsList = apiResponse.data!;
+ for (var location in apiResponse.data!) {
+ if (location.locationType == 1) {
+ hmgHospitalsLocationsList.add(location);
+ } else if (location.locationType == 2) {
+ hmgPharmacyLocationsList.add(location);
+ }
+ }
+ isHMGLocationsListLoading = false;
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+
+ Future getLiveChatProjectsList({Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ isLiveChatProjectsListLoading = true;
+ liveChatProjectsList.clear();
+
+ notifyListeners();
+
+ final result = await contactUsRepo.getLiveChatProjectsList();
+
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(failure: failure),
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ liveChatProjectsList = apiResponse.data!;
+ liveChatProjectsList.sort((a, b) => b.distanceInKilometers.compareTo(a.distanceInKilometers));
+ isLiveChatProjectsListLoading = false;
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+
+ Future insertCOCItem({required String subject, required String message, Function(dynamic)? onSuccess, Function(String)? onError}) async {
+ RequestInsertCOCItem requestInsertCOCItem = RequestInsertCOCItem();
+ requestInsertCOCItem.attachment = feedbackAttachmentList.isNotEmpty ? feedbackAttachmentList.first : "";
+ requestInsertCOCItem.title = subject;
+ requestInsertCOCItem.details = message;
+ requestInsertCOCItem.cOCTypeName = selectedFeedbackType.id.toString();
+ requestInsertCOCItem.formTypeID = selectedFeedbackType.id.toString();
+ requestInsertCOCItem.mobileNo = "966${Utils.getPhoneNumberWithoutZero(appState.getAuthenticatedUser()!.mobileNumber!)}";
+ requestInsertCOCItem.isUserLoggedIn = true;
+ requestInsertCOCItem.projectID = 0;
+ requestInsertCOCItem.patientName = "${appState.getAuthenticatedUser()!.firstName!} ${appState.getAuthenticatedUser()!.lastName!}";
+ requestInsertCOCItem.fileName = "";
+ requestInsertCOCItem.appVersion = ApiConsts.appVersionID;
+ requestInsertCOCItem.uILanguage = appState.isArabic() ? "ar" : "en"; //TODO Change it to be dynamic
+ requestInsertCOCItem.browserInfo = Platform.localHostname;
+ requestInsertCOCItem.deviceInfo = Platform.localHostname;
+ requestInsertCOCItem.resolution = "400x847";
+ requestInsertCOCItem.projectID = 0;
+ requestInsertCOCItem.tokenID = "C0c@@dm!n?T&A&A@Barcha202029582948";
+ requestInsertCOCItem.identificationNo = int.parse(appState.getAuthenticatedUser()!.patientIdentificationNo!);
+ if (BASE_URL.contains('uat')) {
+ requestInsertCOCItem.forDemo = true;
+ } else {
+ requestInsertCOCItem.forDemo = false;
+ }
+
+ final result = await contactUsRepo.insertCOCItem(requestInsertCOCItem: requestInsertCOCItem, patientSelectedAppointment: patientFeedbackSelectedAppointment);
+
+ result.fold(
+ (failure) async => await errorHandlerService.handleError(failure: failure),
+ (apiResponse) {
+ if (apiResponse.messageStatus == 2) {
+ // dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
+ } else if (apiResponse.messageStatus == 1) {
+ notifyListeners();
+ if (onSuccess != null) {
+ onSuccess(apiResponse);
+ }
+ }
+ },
+ );
+ }
+}
diff --git a/lib/features/contact_us/models/feedback_type.dart b/lib/features/contact_us/models/feedback_type.dart
new file mode 100644
index 0000000..ff1025a
--- /dev/null
+++ b/lib/features/contact_us/models/feedback_type.dart
@@ -0,0 +1,11 @@
+class FeedbackType {
+ final int id;
+ final String nameEN;
+ final String nameAR;
+
+ FeedbackType({
+ required this.id,
+ required this.nameEN,
+ required this.nameAR,
+ });
+}
diff --git a/lib/features/contact_us/models/req_models/request_insert_coc_item.dart b/lib/features/contact_us/models/req_models/request_insert_coc_item.dart
new file mode 100644
index 0000000..e285999
--- /dev/null
+++ b/lib/features/contact_us/models/req_models/request_insert_coc_item.dart
@@ -0,0 +1,137 @@
+class RequestInsertCOCItem {
+ bool? isUserLoggedIn;
+ String? mobileNo;
+ int? identificationNo;
+ int? patientID;
+ int? patientOutSA;
+ int? patientTypeID;
+ String? tokenID;
+ String? patientName;
+ int? projectID;
+ String? fileName;
+ String? attachment;
+ String? uILanguage;
+ String? browserInfo;
+ String? cOCTypeName;
+ String? formTypeID;
+ String? details;
+ String? deviceInfo;
+ String? deviceType;
+ String? title;
+ String? resolution;
+ double? versionID;
+ int? channel;
+ int? languageID;
+ String? iPAdress;
+ String? generalid;
+ String? sessionID;
+ bool? isDentalAllowedBackend;
+ int? deviceTypeID;
+ int? patientType;
+ double? appVersion;
+ bool? forDemo;
+
+ RequestInsertCOCItem(
+ {this.isUserLoggedIn,
+ this.mobileNo,
+ this.identificationNo,
+ this.patientID,
+ this.patientOutSA,
+ this.patientTypeID,
+ this.tokenID,
+ this.patientName,
+ this.projectID,
+ this.fileName,
+ this.attachment,
+ this.uILanguage,
+ this.browserInfo,
+ this.cOCTypeName,
+ this.formTypeID,
+ this.details,
+ this.deviceInfo,
+ this.deviceType,
+ this.title,
+ this.resolution,
+ this.versionID,
+ this.channel,
+ this.languageID,
+ this.iPAdress,
+ this.generalid,
+ this.sessionID,
+ this.isDentalAllowedBackend,
+ this.deviceTypeID,
+ this.patientType,
+ this.appVersion,
+ this.forDemo});
+
+ RequestInsertCOCItem.fromJson(Map json) {
+ isUserLoggedIn = json['IsUserLoggedIn'];
+ mobileNo = json['MobileNo'];
+ identificationNo = json['IdentificationNo'];
+ patientID = json['PatientID'];
+ patientOutSA = json['PatientOutSA'];
+ patientTypeID = json['PatientTypeID'];
+ tokenID = json['TokenID'];
+ patientName = json['PatientName'];
+ projectID = json['ProjectID'];
+ fileName = json['FileName'];
+ attachment = json['Attachment'];
+ uILanguage = json['UILanguage'];
+ browserInfo = json['BrowserInfo'];
+ cOCTypeName = json['COCTypeName'];
+ formTypeID = json['FormTypeID'];
+ details = json['Details'];
+ deviceInfo = json['DeviceInfo'];
+ deviceType = json['DeviceType'];
+ title = json['Title'];
+ resolution = json['Resolution'];
+ versionID = json['VersionID'];
+ channel = json['Channel'];
+ languageID = json['LanguageID'];
+ iPAdress = json['IPAdress'];
+ generalid = json['generalid'];
+ sessionID = json['SessionID'];
+ isDentalAllowedBackend = json['isDentalAllowedBackend'];
+ deviceTypeID = json['DeviceTypeID'];
+ patientType = json['PatientType'];
+ appVersion = json['AppVersion'];
+ forDemo = json['ForDemo'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['IsUserLoggedIn'] = this.isUserLoggedIn;
+ data['MobileNo'] = this.mobileNo;
+ data['IdentificationNo'] = this.identificationNo;
+ data['PatientID'] = this.patientID;
+ data['PatientOutSA'] = this.patientOutSA;
+ data['PatientTypeID'] = this.patientTypeID;
+ data['TokenID'] = this.tokenID;
+ data['PatientName'] = this.patientName;
+ data['ProjectID'] = this.projectID;
+ data['FileName'] = this.fileName;
+ data['Attachment'] = this.attachment;
+ data['UILanguage'] = this.uILanguage;
+ data['BrowserInfo'] = this.browserInfo;
+ data['COCTypeName'] = this.cOCTypeName;
+ data['FormTypeID'] = this.formTypeID;
+ data['Details'] = this.details;
+ data['DeviceInfo'] = this.deviceInfo;
+ data['DeviceType'] = this.deviceType;
+ data['Title'] = this.title;
+ data['Resolution'] = this.resolution;
+ data['VersionID'] = this.versionID;
+ data['Channel'] = this.channel;
+ data['LanguageID'] = this.languageID;
+ data['IPAdress'] = this.iPAdress;
+ data['generalid'] = this.generalid;
+ data['SessionID'] = this.sessionID;
+ data['isDentalAllowedBackend'] = this.isDentalAllowedBackend;
+ data['DeviceTypeID'] = this.deviceTypeID;
+ data['PatientType'] = this.patientType;
+ data['AppVersion'] = this.appVersion;
+ data['ForDemo'] = this.forDemo;
+
+ return data;
+ }
+}
diff --git a/lib/features/contact_us/models/resp_models/get_hmg_locations.dart b/lib/features/contact_us/models/resp_models/get_hmg_locations.dart
new file mode 100644
index 0000000..d15b853
--- /dev/null
+++ b/lib/features/contact_us/models/resp_models/get_hmg_locations.dart
@@ -0,0 +1,80 @@
+class GetHMGLocationsModel {
+ dynamic cityID;
+ String? cityName;
+ dynamic cityNameN;
+ dynamic distanceInKilometers;
+ bool? isActive;
+ String? latitude;
+ int? locationID;
+ String? locationName;
+ dynamic locationNameN;
+ dynamic locationType;
+ String? longitude;
+ int? pharmacyLocationID;
+ String? phoneNumber;
+ int? projectID;
+ String? projectImageURL;
+ int? setupID;
+ dynamic sortOrder;
+
+ GetHMGLocationsModel(
+ {this.cityID,
+ this.cityName,
+ this.cityNameN,
+ this.distanceInKilometers,
+ this.isActive,
+ this.latitude,
+ this.locationID,
+ this.locationName,
+ this.locationNameN,
+ this.locationType,
+ this.longitude,
+ this.pharmacyLocationID,
+ this.phoneNumber,
+ this.projectID,
+ this.projectImageURL,
+ this.setupID,
+ this.sortOrder});
+
+ GetHMGLocationsModel.fromJson(Map json) {
+ cityID = json['CityID'];
+ cityName = json['CityName'];
+ cityNameN = json['CityNameN'];
+ distanceInKilometers = json['DistanceInKilometers'];
+ isActive = json['IsActive'];
+ latitude = json['Latitude'];
+ locationID = json['LocationID'];
+ locationName = json['LocationName'];
+ locationNameN = json['LocationNameN'];
+ locationType = json['LocationType'];
+ longitude = json['Longitude'];
+ pharmacyLocationID = json['PharmacyLocationID'];
+ phoneNumber = json['PhoneNumber'];
+ projectID = json['ProjectID'];
+ projectImageURL = json['ProjectImageURL'];
+ setupID = json['SetupID'];
+ sortOrder = json['SortOrder'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['CityID'] = this.cityID;
+ data['CityName'] = this.cityName;
+ data['CityNameN'] = this.cityNameN;
+ data['DistanceInKilometers'] = this.distanceInKilometers;
+ data['IsActive'] = this.isActive;
+ data['Latitude'] = this.latitude;
+ data['LocationID'] = this.locationID;
+ data['LocationName'] = this.locationName;
+ data['LocationNameN'] = this.locationNameN;
+ data['LocationType'] = this.locationType;
+ data['Longitude'] = this.longitude;
+ data['PharmacyLocationID'] = this.pharmacyLocationID;
+ data['PhoneNumber'] = this.phoneNumber;
+ data['ProjectID'] = this.projectID;
+ data['ProjectImageURL'] = this.projectImageURL;
+ data['SetupID'] = this.setupID;
+ data['SortOrder'] = this.sortOrder;
+ return data;
+ }
+}
\ No newline at end of file
diff --git a/lib/features/contact_us/models/resp_models/get_patient_ic_projects.dart b/lib/features/contact_us/models/resp_models/get_patient_ic_projects.dart
new file mode 100644
index 0000000..ba7463f
--- /dev/null
+++ b/lib/features/contact_us/models/resp_models/get_patient_ic_projects.dart
@@ -0,0 +1,48 @@
+import 'package:hmg_patient_app_new/core/utils/date_util.dart';
+
+class GetPatientICProjectsModel {
+ int? id;
+ String? projectName;
+ String? projectNameN;
+ String? value;
+ dynamic languageId;
+ DateTime? createdOn;
+ String? createdBy;
+ dynamic editedOn;
+ dynamic editedBy;
+ bool? isActive;
+ dynamic distanceInKilometers;
+
+ GetPatientICProjectsModel(
+ {this.id, this.projectName, this.projectNameN, this.value, this.languageId, this.createdOn, this.createdBy, this.editedOn, this.editedBy, this.distanceInKilometers, this.isActive});
+
+ GetPatientICProjectsModel.fromJson(Map json) {
+ id = json['id'];
+ projectName = json['ProjectName'];
+ projectNameN = json['ProjectNameN'];
+ value = json['Value'];
+ languageId = json['LanguageId'];
+ createdOn = DateUtil.convertStringToDate(json['CreatedOn']);
+ createdBy = json['CreatedBy'];
+ editedOn = json['EditedOn'];
+ editedBy = json['EditedBy'];
+ isActive = json['IsActive'];
+ distanceInKilometers = json['DistanceInKilometers'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['id'] = this.id;
+ data['ProjectName'] = this.projectName;
+ data['ProjectNameN'] = this.projectNameN;
+ data['Value'] = this.value;
+ data['LanguageId'] = this.languageId;
+ data['CreatedOn'] = this.createdOn;
+ data['CreatedBy'] = this.createdBy;
+ data['EditedOn'] = this.editedOn;
+ data['EditedBy'] = this.editedBy;
+ data['IsActive'] = this.isActive;
+ data['DistanceInKilometers'] = this.distanceInKilometers;
+ return data;
+ }
+}
diff --git a/lib/features/emergency_services/emergency_services_repo.dart b/lib/features/emergency_services/emergency_services_repo.dart
index 65594b8..c63f0ee 100644
--- a/lib/features/emergency_services/emergency_services_repo.dart
+++ b/lib/features/emergency_services/emergency_services_repo.dart
@@ -1,11 +1,18 @@
+import 'dart:developer';
+
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/core/utils/date_util.dart';
+import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/request_model/PatientER_RC.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/request_model/RRTRequestModel.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/AmbulanceRequestOrdersModel.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/EROnlineCheckInPaymentDetailsResponse.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/ProjectAvgERWaitingTime.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/RRTServiceData.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/rrt_procedures_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
@@ -13,20 +20,44 @@ import 'package:hmg_patient_app_new/services/logger_service.dart';
import 'models/resp_model/PatientERTransportationMethod.dart';
abstract class EmergencyServicesRepo {
- Future>>> getRRTProcedures();
+ Future>>> getRRTProcedures(int languageId);
Future>>> getNearestEr({int? id, int? projectID});
- Future>>> getTransportationMethods({int? id});
+ Future>> checkPatientERAdvanceBalance();
Future>>> getProjectList();
+ Future>> checkPatientERPaymentInformation({int projectID});
+
+ Future>> createAdvancePaymentForER(
+ {required int projectID,
+ required AuthenticatedUser authUser,
+ required num paymentAmount,
+ required String paymentMethodName,
+ required String paymentReference});
+
+ Future>> addAdvanceNumberRequest(
+ {required String advanceNumber, required String paymentReference, required String appointmentNo});
+
+ Future>> getProjectIDFromNFC({required String nfcCode});
+
+ Future>> autoGenerateInvoiceERClinic({required int projectID});
+
+ Future>>> getTransportationMethods({int? id});
+
Future>> submitAmbulanceRequest(PatientER_RC request);
Future>>> getTransportationOrders({int? id});
Future>> cancelOrder(int? iD, int patientId);
+ Future>> submitRRTRequest(RRTRequestModel request);
+
+ Future>> getRRTOrders({int? id});
+
+ Future>> cancelRRTOrder(int? iD);
+ Future>> getTermsAndCondition();
}
class EmergencyServicesRepoImp implements EmergencyServicesRepo {
@@ -51,7 +82,8 @@ class EmergencyServicesRepoImp implements EmergencyServicesRepo {
try {
final list = response['List_ProjectAvgERWaitingTime'];
- final clinicsList = list.map((item) => ProjectAvgERWaitingTime.fromJson(item as Map)).toList().cast();
+ final clinicsList =
+ list.map((item) => ProjectAvgERWaitingTime.fromJson(item as Map)).toList().cast();
apiResponse = GenericApiModel>(
messageStatus: messageStatus,
statusCode: statusCode,
@@ -72,8 +104,8 @@ class EmergencyServicesRepoImp implements EmergencyServicesRepo {
}
@override
- Future>>> getRRTProcedures() async {
- Map mapDevice = {};
+ Future>>> getRRTProcedures(int languageId) async {
+ Map mapDevice = {"ProjectID": 15, "languageID":1};
try {
GenericApiModel>? apiResponse;
@@ -87,7 +119,8 @@ class EmergencyServicesRepoImp implements EmergencyServicesRepo {
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = response['Vida_ProcedureList'];
- final proceduresList = list.map((item) => RRTProceduresResponseModel.fromJson(item as Map)).toList().cast();
+ final proceduresList =
+ list.map((item) => RRTProceduresResponseModel.fromJson(item as Map)).toList().cast();
apiResponse = GenericApiModel>(
messageStatus: messageStatus,
@@ -124,7 +157,10 @@ class EmergencyServicesRepoImp implements EmergencyServicesRepo {
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = response['response']['transportationservices'];
- final proceduresList = list.map((item) => PatientERTransportationMethod.fromJson(item as Map)).toList().cast();
+ final proceduresList = list
+ .map((item) => PatientERTransportationMethod.fromJson(item as Map))
+ .toList()
+ .cast();
apiResponse = GenericApiModel>(
messageStatus: messageStatus,
@@ -223,7 +259,7 @@ class EmergencyServicesRepoImp implements EmergencyServicesRepo {
Failure? failure;
await apiClient.post(
body: {},
- "$GET_ALL_TRANSPORTATIONS_ORDERS?patientID=$id",
+ "$GET_ALL_TRANSPORTATIONS_ORDERS?patientID=$id",
isRCService: true,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
@@ -231,7 +267,8 @@ class EmergencyServicesRepoImp implements EmergencyServicesRepo {
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = response['response'];
- final proceduresList = list.map((item) => AmbulanceRequestOrdersModel.fromJson(item as Map)).toList().cast();
+ final proceduresList =
+ list.map((item) => AmbulanceRequestOrdersModel.fromJson(item as Map)).toList().cast();
apiResponse = GenericApiModel>(
messageStatus: messageStatus,
@@ -290,4 +327,395 @@ class EmergencyServicesRepoImp implements EmergencyServicesRepo {
return Left(UnknownFailure(e.toString()));
}
}
+
+ @override
+ Future> checkPatientERAdvanceBalance() async {
+ Map mapDevice = {"ClinicID": 10};
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ CHECK_PATIENT_ER_ADVANCE_BALANCE,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) => failure = failureType,
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final bool patientHasERBalance = response['BalanceAmount'] > 0;
+ log(patientHasERBalance.toString());
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: patientHasERBalance,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>> checkPatientERPaymentInformation({int? projectID}) async {
+ Map mapDevice = {"ClinicID": 10, "ProjectID": projectID ?? 0};
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_ER_ONLINE_PAYMENT_DETAILS,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final erOnlineCheckInPaymentDetailsResponse = EROnlineCheckInPaymentDetailsResponse.fromJson(response["ResponsePatientShare"]);
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: erOnlineCheckInPaymentDetailsResponse,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future> createAdvancePaymentForER(
+ {required int projectID,
+ required AuthenticatedUser authUser,
+ required num paymentAmount,
+ required String paymentMethodName,
+ required String paymentReference}) async {
+ Map mapDevice = {
+ "LanguageID": 1,
+ "ERAdvanceAmount": {
+ "ProjectId": projectID,
+ "PatientId": authUser.patientId,
+ "ClinicId": 10,
+ "DepositorName": "${authUser.firstName!} ${authUser.lastName!}",
+ "MemberId": authUser.patientId,
+ "NationalityID": authUser.nationalityId,
+ "PaymentAmount": paymentAmount,
+ "PaymentDate": DateUtil.convertDateToString(DateTime.now()),
+ "PaymentMethodName": paymentMethodName,
+ "PaymentReferenceNumber": paymentReference,
+ "SourceType": 2
+ }
+ };
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ ER_CREATE_ADVANCE_PAYMENT,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final vidaAdvanceNumber = response['ER_AdvancePaymentResponse']['AdvanceNumber'].toString();
+ log(vidaAdvanceNumber);
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: vidaAdvanceNumber,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future> addAdvanceNumberRequest(
+ {required String advanceNumber, required String paymentReference, required String appointmentNo}) async {
+ Map requestBody = {
+ "AdvanceNumber": advanceNumber,
+ "AdvanceNumber_VP": advanceNumber,
+ "PaymentReferenceNumber": paymentReference,
+ "AppointmentID": appointmentNo,
+ };
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ ADD_ADVANCE_NUMBER_REQUEST,
+ body: requestBody,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: response,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>> getProjectIDFromNFC({required String nfcCode}) async {
+ Map mapDevice = {"nFC_Code": nfcCode};
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ GET_PROJECT_FROM_NFC,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final projectID = response['GetProjectByNFC'][0]["ProjectID"];
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: projectID,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>> autoGenerateInvoiceERClinic({required int projectID}) async {
+ Map mapDevice = {
+ "ProjectID": projectID,
+ "ClinicID": "10",
+ "IsAdvanceAvailable": true,
+ "MemberID": 102,
+ "PaymentMethod": "VISA",
+ };
+
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ AUTO_GENERATE_INVOICE_ER,
+ body: mapDevice,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: true,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>> submitRRTRequest(RRTRequestModel request) async {
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ body: request.toJson(),
+ ADD_RRT_ORDER_RC,
+ isRCService: true,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: true,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>> cancelRRTOrder(int? iD) async{
+ try {
+ GenericApiModel? apiResponse;
+
+ Map request = {"Id": iD, "ClickButton": 14};
+
+ Failure? failure;
+ await apiClient.post(
+ body: request,
+ UPDATE_RRT_ORDER_RC,
+ isRCService: true,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: true,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+
+ }
+
+ @override
+ Future>> getRRTOrders({int? id}) async {
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ body: {},
+ GET_ALL_RRT_ORDERS_RC,
+ isRCService: true,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final list = response['response'];
+
+ RRTServiceData serviceData = RRTServiceData();
+ list.forEach((item) {
+ if (item["StatusId"] == 1 || item["StatusId"] == 2) {
+ // Pending
+ serviceData.pendingOrders.add(GetCMCAllOrdersResponseModel.fromJson(item));
+ }
+ serviceData.completedOrders.add(GetCMCAllOrdersResponseModel.fromJson(item));
+ });
+
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: serviceData,
+ );
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+ }
+
+ @override
+ Future>> getTermsAndCondition() async {
+ try {
+ GenericApiModel? apiResponse;
+ Failure? failure;
+ await apiClient.post(
+ body: {},
+ GET_USER_TERMS,
+ onFailure: (error, statusCode, {messageStatus, failureType}) {
+ failure = failureType;
+ },
+ onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
+ try {
+ final agreement = response['UserAgreementContent'];
+ apiResponse = GenericApiModel(
+ messageStatus: messageStatus,
+ statusCode: statusCode,
+ errorMessage: null,
+ data: agreement,
+ );
+
+ } catch (e) {
+ failure = DataParsingFailure(e.toString());
+ }
+ },
+ );
+ if (failure != null) return Left(failure!);
+ if (apiResponse == null) return Left(ServerFailure("Unknown error"));
+ return Right(apiResponse!);
+ } catch (e) {
+ return Left(UnknownFailure(e.toString()));
+ }
+
+ }
+
+
}
diff --git a/lib/features/emergency_services/emergency_services_view_model.dart b/lib/features/emergency_services/emergency_services_view_model.dart
index 0b28c2a..400eb04 100644
--- a/lib/features/emergency_services/emergency_services_view_model.dart
+++ b/lib/features/emergency_services/emergency_services_view_model.dart
@@ -2,39 +2,53 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart' as GMSMapServices;
-
+import 'package:hmg_patient_app_new/core/app_assets.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/location_util.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
-import 'package:hmg_patient_app_new/core/utils/doctor_response_mapper.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/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/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/emergency_services/emergency_services_repo.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/AmbulanceCallingPlace.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/OrderDisplay.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/request_model/PatientER_RC.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/request_model/RRTRequestModel.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/AmbulanceRequestOrdersModel.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/EROnlineCheckInPaymentDetailsResponse.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/PatientERTransportationMethod.dart'
show PatientERTransportationMethod;
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/ProjectAvgERWaitingTime.dart';
+import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/RRTServiceData.dart';
import 'package:hmg_patient_app_new/features/emergency_services/models/resp_model/rrt_procedures_response_model.dart';
import 'package:hmg_patient_app_new/features/location/PlaceDetails.dart' show PlaceDetails;
import 'package:hmg_patient_app_new/features/location/PlacePrediction.dart';
+import 'package:hmg_patient_app_new/features/location/location_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/facility_selection.dart';
-import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_repo.dart';
-import 'package:hmg_patient_app_new/presentation/authentication/login.dart';
+import 'package:hmg_patient_app_new/presentation/emergency_services/RRT/rrt_request_type_select.dart';
+import 'package:hmg_patient_app_new/presentation/emergency_services/RRT/terms_and_condition.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/call_ambulance_page.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/requesting_services_page.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/call_ambulance/tracking_screen.dart';
+import 'package:hmg_patient_app_new/presentation/emergency_services/er_online_checkin/er_online_checkin_home.dart';
+import 'package:hmg_patient_app_new/presentation/emergency_services/er_online_checkin/er_online_checkin_payment_details_page.dart';
import 'package:hmg_patient_app_new/presentation/emergency_services/nearest_er_page.dart';
import 'package:hmg_patient_app_new/routes/app_routes.dart' show AppRoutes;
import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/error_handler_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/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/expandable_bottom_sheet/model/BottomSheetType.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
+import 'package:hmg_patient_app_new/widgets/map/map_utility_screen.dart';
import 'package:hmg_patient_app_new/widgets/order_tracking/order_tracking_state.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:huawei_map/huawei_map.dart' as HMSCameraServices;
@@ -64,8 +78,6 @@ class EmergencyServicesViewModel extends ChangeNotifier {
List