diff --git a/assets/images/svg/insurance.svg b/assets/images/svg/insurance.svg new file mode 100644 index 0000000..c8d3c38 --- /dev/null +++ b/assets/images/svg/insurance.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/svg/more.svg b/assets/images/svg/more.svg new file mode 100644 index 0000000..4dbe5fd --- /dev/null +++ b/assets/images/svg/more.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/svg/requests.svg b/assets/images/svg/requests.svg new file mode 100644 index 0000000..7d90098 --- /dev/null +++ b/assets/images/svg/requests.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ios/Podfile.lock b/ios/Podfile.lock deleted file mode 100644 index c62a44f..0000000 --- a/ios/Podfile.lock +++ /dev/null @@ -1,457 +0,0 @@ -PODS: - - audio_session (0.0.1): - - Flutter - - connectivity_plus (0.0.1): - - Flutter - - device_calendar (0.0.1): - - Flutter - - device_info_plus (0.0.1): - - Flutter - - DKImagePickerController/Core (4.3.9): - - DKImagePickerController/ImageDataManager - - DKImagePickerController/Resource - - DKImagePickerController/ImageDataManager (4.3.9) - - DKImagePickerController/PhotoGallery (4.3.9): - - DKImagePickerController/Core - - DKPhotoGallery - - DKImagePickerController/Resource (4.3.9) - - DKPhotoGallery (0.0.19): - - DKPhotoGallery/Core (= 0.0.19) - - DKPhotoGallery/Model (= 0.0.19) - - DKPhotoGallery/Preview (= 0.0.19) - - DKPhotoGallery/Resource (= 0.0.19) - - SDWebImage - - SwiftyGif - - DKPhotoGallery/Core (0.0.19): - - DKPhotoGallery/Model - - DKPhotoGallery/Preview - - SDWebImage - - SwiftyGif - - DKPhotoGallery/Model (0.0.19): - - SDWebImage - - SwiftyGif - - DKPhotoGallery/Preview (0.0.19): - - DKPhotoGallery/Model - - DKPhotoGallery/Resource - - SDWebImage - - SwiftyGif - - DKPhotoGallery/Resource (0.0.19): - - SDWebImage - - SwiftyGif - - file_picker (0.0.1): - - DKImagePickerController/PhotoGallery - - Flutter - - Firebase/Analytics (11.15.0): - - Firebase/Core - - Firebase/Core (11.15.0): - - Firebase/CoreOnly - - FirebaseAnalytics (~> 11.15.0) - - Firebase/CoreOnly (11.15.0): - - FirebaseCore (~> 11.15.0) - - Firebase/Messaging (11.15.0): - - Firebase/CoreOnly - - FirebaseMessaging (~> 11.15.0) - - firebase_analytics (11.6.0): - - Firebase/Analytics (= 11.15.0) - - firebase_core - - Flutter - - firebase_core (3.15.2): - - Firebase/CoreOnly (= 11.15.0) - - Flutter - - firebase_messaging (15.2.10): - - Firebase/Messaging (= 11.15.0) - - firebase_core - - Flutter - - FirebaseAnalytics (11.15.0): - - FirebaseAnalytics/Default (= 11.15.0) - - FirebaseCore (~> 11.15.0) - - FirebaseInstallations (~> 11.0) - - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - - GoogleUtilities/MethodSwizzler (~> 8.1) - - GoogleUtilities/Network (~> 8.1) - - "GoogleUtilities/NSData+zlib (~> 8.1)" - - nanopb (~> 3.30910.0) - - FirebaseAnalytics/Default (11.15.0): - - FirebaseCore (~> 11.15.0) - - FirebaseInstallations (~> 11.0) - - GoogleAppMeasurement/Default (= 11.15.0) - - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - - GoogleUtilities/MethodSwizzler (~> 8.1) - - GoogleUtilities/Network (~> 8.1) - - "GoogleUtilities/NSData+zlib (~> 8.1)" - - nanopb (~> 3.30910.0) - - FirebaseCore (11.15.0): - - FirebaseCoreInternal (~> 11.15.0) - - GoogleUtilities/Environment (~> 8.1) - - GoogleUtilities/Logger (~> 8.1) - - FirebaseCoreInternal (11.15.0): - - "GoogleUtilities/NSData+zlib (~> 8.1)" - - FirebaseInstallations (11.15.0): - - FirebaseCore (~> 11.15.0) - - GoogleUtilities/Environment (~> 8.1) - - GoogleUtilities/UserDefaults (~> 8.1) - - PromisesObjC (~> 2.4) - - FirebaseMessaging (11.15.0): - - FirebaseCore (~> 11.15.0) - - FirebaseInstallations (~> 11.0) - - GoogleDataTransport (~> 10.0) - - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - - GoogleUtilities/Environment (~> 8.1) - - GoogleUtilities/Reachability (~> 8.1) - - GoogleUtilities/UserDefaults (~> 8.1) - - nanopb (~> 3.30910.0) - - FLAnimatedImage (1.0.17) - - Flutter (1.0.0) - - flutter_inappwebview_ios (0.0.1): - - Flutter - - flutter_inappwebview_ios/Core (= 0.0.1) - - OrderedSet (~> 6.0.3) - - flutter_inappwebview_ios/Core (0.0.1): - - Flutter - - OrderedSet (~> 6.0.3) - - flutter_ios_voip_kit_karmm (0.8.0): - - Flutter - - flutter_local_notifications (0.0.1): - - Flutter - - flutter_zoom_videosdk (0.0.1): - - Flutter - - ZoomVideoSDK/CptShare (= 2.1.10) - - ZoomVideoSDK/zm_annoter_dynamic (= 2.1.10) - - ZoomVideoSDK/zoomcml (= 2.1.10) - - ZoomVideoSDK/ZoomVideoSDK (= 2.1.10) - - fluttertoast (0.0.2): - - Flutter - - geolocator_apple (1.2.0): - - Flutter - - FlutterMacOS - - Google-Maps-iOS-Utils (5.0.0): - - GoogleMaps (~> 8.0) - - google_maps_flutter_ios (0.0.1): - - Flutter - - Google-Maps-iOS-Utils (< 7.0, >= 5.0) - - GoogleMaps (< 10.0, >= 8.4) - - GoogleAdsOnDeviceConversion (2.1.0): - - GoogleUtilities/Logger (~> 8.1) - - GoogleUtilities/Network (~> 8.1) - - nanopb (~> 3.30910.0) - - GoogleAppMeasurement/Core (11.15.0): - - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - - GoogleUtilities/MethodSwizzler (~> 8.1) - - GoogleUtilities/Network (~> 8.1) - - "GoogleUtilities/NSData+zlib (~> 8.1)" - - nanopb (~> 3.30910.0) - - GoogleAppMeasurement/Default (11.15.0): - - GoogleAdsOnDeviceConversion (= 2.1.0) - - GoogleAppMeasurement/Core (= 11.15.0) - - GoogleAppMeasurement/IdentitySupport (= 11.15.0) - - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - - GoogleUtilities/MethodSwizzler (~> 8.1) - - GoogleUtilities/Network (~> 8.1) - - "GoogleUtilities/NSData+zlib (~> 8.1)" - - nanopb (~> 3.30910.0) - - GoogleAppMeasurement/IdentitySupport (11.15.0): - - GoogleAppMeasurement/Core (= 11.15.0) - - GoogleUtilities/AppDelegateSwizzler (~> 8.1) - - GoogleUtilities/MethodSwizzler (~> 8.1) - - GoogleUtilities/Network (~> 8.1) - - "GoogleUtilities/NSData+zlib (~> 8.1)" - - nanopb (~> 3.30910.0) - - GoogleDataTransport (10.1.0): - - nanopb (~> 3.30910.0) - - PromisesObjC (~> 2.4) - - GoogleMaps (8.4.0): - - GoogleMaps/Maps (= 8.4.0) - - GoogleMaps/Base (8.4.0) - - GoogleMaps/Maps (8.4.0): - - GoogleMaps/Base - - GoogleUtilities/AppDelegateSwizzler (8.1.0): - - GoogleUtilities/Environment - - GoogleUtilities/Logger - - GoogleUtilities/Network - - GoogleUtilities/Privacy - - GoogleUtilities/Environment (8.1.0): - - GoogleUtilities/Privacy - - GoogleUtilities/Logger (8.1.0): - - GoogleUtilities/Environment - - GoogleUtilities/Privacy - - GoogleUtilities/MethodSwizzler (8.1.0): - - GoogleUtilities/Logger - - GoogleUtilities/Privacy - - GoogleUtilities/Network (8.1.0): - - GoogleUtilities/Logger - - "GoogleUtilities/NSData+zlib" - - GoogleUtilities/Privacy - - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (8.1.0)": - - GoogleUtilities/Privacy - - GoogleUtilities/Privacy (8.1.0) - - GoogleUtilities/Reachability (8.1.0): - - GoogleUtilities/Logger - - GoogleUtilities/Privacy - - GoogleUtilities/UserDefaults (8.1.0): - - GoogleUtilities/Logger - - GoogleUtilities/Privacy - - health (13.1.3): - - Flutter - - image_picker_ios (0.0.1): - - Flutter - - just_audio (0.0.1): - - Flutter - - FlutterMacOS - - local_auth_darwin (0.0.1): - - Flutter - - FlutterMacOS - - manage_calendar_events (0.0.1): - - Flutter - - MapboxCommon (23.11.0) - - MapboxCoreMaps (10.19.1): - - MapboxCommon (~> 23.11) - - MapboxCoreNavigation (2.19.0): - - MapboxDirections (~> 2.14) - - MapboxNavigationNative (< 207.0.0, >= 206.0.1) - - MapboxDirections (2.14.2): - - Polyline (~> 5.0) - - Turf (~> 2.8.0) - - MapboxMaps (10.19.0): - - MapboxCommon (= 23.11.0) - - MapboxCoreMaps (= 10.19.1) - - MapboxMobileEvents (= 2.0.0) - - Turf (= 2.8.0) - - MapboxMobileEvents (2.0.0) - - MapboxNavigation (2.19.0): - - MapboxCoreNavigation (= 2.19.0) - - MapboxMaps (~> 10.18) - - MapboxSpeech (~> 2.0) - - Solar-dev (~> 3.0) - - MapboxNavigationNative (206.2.2): - - MapboxCommon (~> 23.10) - - MapboxSpeech (2.1.1) - - nanopb (3.30910.0): - - nanopb/decode (= 3.30910.0) - - nanopb/encode (= 3.30910.0) - - nanopb/decode (3.30910.0) - - nanopb/encode (3.30910.0) - - OrderedSet (6.0.3) - - package_info_plus (0.4.5): - - Flutter - - path_provider_foundation (0.0.1): - - Flutter - - FlutterMacOS - - permission_handler_apple (9.3.0): - - Flutter - - Polyline (5.1.0) - - PromisesObjC (2.4.0) - - SDWebImage (5.21.2): - - SDWebImage/Core (= 5.21.2) - - SDWebImage/Core (5.21.2) - - share_plus (0.0.1): - - Flutter - - shared_preferences_foundation (0.0.1): - - Flutter - - FlutterMacOS - - Solar-dev (3.0.1) - - sqflite_darwin (0.0.4): - - Flutter - - FlutterMacOS - - SwiftyGif (5.4.5) - - Turf (2.8.0) - - url_launcher_ios (0.0.1): - - Flutter - - ZoomVideoSDK/CptShare (2.1.10) - - ZoomVideoSDK/zm_annoter_dynamic (2.1.10) - - ZoomVideoSDK/zoomcml (2.1.10) - - ZoomVideoSDK/ZoomVideoSDK (2.1.10) - -DEPENDENCIES: - - audio_session (from `.symlinks/plugins/audio_session/ios`) - - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) - - device_calendar (from `.symlinks/plugins/device_calendar/ios`) - - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - - file_picker (from `.symlinks/plugins/file_picker/ios`) - - firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`) - - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) - - FLAnimatedImage - - Flutter (from `Flutter`) - - flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`) - - flutter_ios_voip_kit_karmm (from `.symlinks/plugins/flutter_ios_voip_kit_karmm/ios`) - - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) - - flutter_zoom_videosdk (from `.symlinks/plugins/flutter_zoom_videosdk/ios`) - - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - - geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`) - - google_maps_flutter_ios (from `.symlinks/plugins/google_maps_flutter_ios/ios`) - - health (from `.symlinks/plugins/health/ios`) - - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - - just_audio (from `.symlinks/plugins/just_audio/darwin`) - - local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`) - - manage_calendar_events (from `.symlinks/plugins/manage_calendar_events/ios`) - - MapboxMaps (= 10.19.0) - - MapboxNavigation (= 2.19.0) - - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - - share_plus (from `.symlinks/plugins/share_plus/ios`) - - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`) - - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - -SPEC REPOS: - trunk: - - DKImagePickerController - - DKPhotoGallery - - Firebase - - FirebaseAnalytics - - FirebaseCore - - FirebaseCoreInternal - - FirebaseInstallations - - FirebaseMessaging - - FLAnimatedImage - - Google-Maps-iOS-Utils - - GoogleAdsOnDeviceConversion - - GoogleAppMeasurement - - GoogleDataTransport - - GoogleMaps - - GoogleUtilities - - MapboxCommon - - MapboxCoreMaps - - MapboxCoreNavigation - - MapboxDirections - - MapboxMaps - - MapboxMobileEvents - - MapboxNavigation - - MapboxNavigationNative - - MapboxSpeech - - nanopb - - OrderedSet - - Polyline - - PromisesObjC - - SDWebImage - - Solar-dev - - SwiftyGif - - Turf - - ZoomVideoSDK - -EXTERNAL SOURCES: - audio_session: - :path: ".symlinks/plugins/audio_session/ios" - connectivity_plus: - :path: ".symlinks/plugins/connectivity_plus/ios" - device_calendar: - :path: ".symlinks/plugins/device_calendar/ios" - device_info_plus: - :path: ".symlinks/plugins/device_info_plus/ios" - file_picker: - :path: ".symlinks/plugins/file_picker/ios" - firebase_analytics: - :path: ".symlinks/plugins/firebase_analytics/ios" - firebase_core: - :path: ".symlinks/plugins/firebase_core/ios" - firebase_messaging: - :path: ".symlinks/plugins/firebase_messaging/ios" - Flutter: - :path: Flutter - flutter_inappwebview_ios: - :path: ".symlinks/plugins/flutter_inappwebview_ios/ios" - flutter_ios_voip_kit_karmm: - :path: ".symlinks/plugins/flutter_ios_voip_kit_karmm/ios" - flutter_local_notifications: - :path: ".symlinks/plugins/flutter_local_notifications/ios" - flutter_zoom_videosdk: - :path: ".symlinks/plugins/flutter_zoom_videosdk/ios" - fluttertoast: - :path: ".symlinks/plugins/fluttertoast/ios" - geolocator_apple: - :path: ".symlinks/plugins/geolocator_apple/darwin" - google_maps_flutter_ios: - :path: ".symlinks/plugins/google_maps_flutter_ios/ios" - health: - :path: ".symlinks/plugins/health/ios" - image_picker_ios: - :path: ".symlinks/plugins/image_picker_ios/ios" - just_audio: - :path: ".symlinks/plugins/just_audio/darwin" - local_auth_darwin: - :path: ".symlinks/plugins/local_auth_darwin/darwin" - manage_calendar_events: - :path: ".symlinks/plugins/manage_calendar_events/ios" - package_info_plus: - :path: ".symlinks/plugins/package_info_plus/ios" - path_provider_foundation: - :path: ".symlinks/plugins/path_provider_foundation/darwin" - permission_handler_apple: - :path: ".symlinks/plugins/permission_handler_apple/ios" - share_plus: - :path: ".symlinks/plugins/share_plus/ios" - shared_preferences_foundation: - :path: ".symlinks/plugins/shared_preferences_foundation/darwin" - sqflite_darwin: - :path: ".symlinks/plugins/sqflite_darwin/darwin" - url_launcher_ios: - :path: ".symlinks/plugins/url_launcher_ios/ios" - -SPEC CHECKSUMS: - audio_session: 19e9480dbdd4e5f6c4543826b2e8b0e4ab6145fe - connectivity_plus: 2a701ffec2c0ae28a48cf7540e279787e77c447d - device_calendar: 9cb33f88a02e19652ec7b8b122ca778f751b1f7b - device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342 - DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c - DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 - file_picker: b159e0c068aef54932bb15dc9fd1571818edaf49 - Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e - firebase_analytics: bf93e20703c95030404d6ddbb1adf05bf5c3885b - firebase_core: 99a37263b3c27536063a7b601d9e2a49400a433c - firebase_messaging: bf6697c61f31c7cc0f654131212ff04c0115c2c7 - FirebaseAnalytics: 6433dfd311ba78084fc93bdfc145e8cb75740eae - FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e - FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4 - FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843 - FirebaseMessaging: 3b26e2cee503815e01c3701236b020aa9b576f09 - FLAnimatedImage: bbf914596368867157cc71b38a8ec834b3eeb32b - Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 - flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4 - flutter_ios_voip_kit_karmm: 7ea37381a8841c92d186edf1f4604df5cc437579 - flutter_local_notifications: ff50f8405aaa0ccdc7dcfb9022ca192e8ad9688f - flutter_zoom_videosdk: 7ddc97d617b85aeace252165d2b5fc5638678c38 - fluttertoast: 21eecd6935e7064cc1fcb733a4c5a428f3f24f0f - geolocator_apple: 66b711889fd333205763b83c9dcf0a57a28c7afd - Google-Maps-iOS-Utils: 66d6de12be1ce6d3742a54661e7a79cb317a9321 - google_maps_flutter_ios: e31555a04d1986ab130f2b9f24b6cdc861acc6d3 - GoogleAdsOnDeviceConversion: 2be6297a4f048459e0ae17fad9bfd2844e10cf64 - GoogleAppMeasurement: 700dce7541804bec33db590a5c496b663fbe2539 - GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 - GoogleMaps: 8939898920281c649150e0af74aa291c60f2e77d - GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 - health: f1207cccb625fc2e8af263b09c29661bde7b0b7e - image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 - just_audio: a42c63806f16995daf5b219ae1d679deb76e6a79 - local_auth_darwin: fa4b06454df7df8e97c18d7ee55151c57e7af0de - manage_calendar_events: 9b2889799340398027b3e3f5c4891d41599ec257 - MapboxCommon: 119f3759f7dc9457f0695848108ab323eb643cb4 - MapboxCoreMaps: ca17f67baced23f8c952166ac6314c35bad3f66c - MapboxCoreNavigation: 3be9990fae3ed732a101001746d0e3b4234ec023 - MapboxDirections: d4fe7d43cff82aa0c15955d1b4563a5a01e2d4de - MapboxMaps: b7f29ec7c33f7dc6d2947c1148edce6db81db9a7 - MapboxMobileEvents: d044b9edbe0ec7df60f6c2c9634fe9a7f449266b - MapboxNavigation: da9cf3d773ed5b0fa0fb388fccdaa117ee681f31 - MapboxNavigationNative: 629e359f3d2590acd1ebbacaaf99e1a80ee57e42 - MapboxSpeech: cd25ef99c3a3d2e0da72620ff558276ea5991a77 - nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 - OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94 - package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 - path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 - permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 - Polyline: 2a1f29f87f8d9b7de868940f4f76deb8c678a5b1 - PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 - SDWebImage: 9f177d83116802728e122410fb25ad88f5c7608a - share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f - shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 - Solar-dev: 4612dc9878b9fed2667d23b327f1d4e54e16e8d0 - sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d - SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 - Turf: aa2ede4298009639d10db36aba1a7ebaad072a5e - url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe - ZoomVideoSDK: 94e939820e57a075c5e712559f927017da0de06a - -PODFILE CHECKSUM: 5df9d8aa8f2c105eacd5ad7a310503d93c68c86b - -COCOAPODS: 1.16.2 diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart index d43ca93..a6f033c 100644 --- a/lib/core/api/api_client.dart +++ b/lib/core/api/api_client.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:convert'; import 'dart:developer'; -import 'dart:io' show Platform; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/api_consts.dart'; @@ -9,7 +8,6 @@ import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/services/analytics/analytics_service.dart'; -import 'package:hmg_patient_app_new/services/dialog_service.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:http/http.dart' as http; @@ -19,7 +17,7 @@ abstract class ApiClient { Future post( String endPoint, { required Map body, - required Function(dynamic response, int statusCode, {int? messageStatus}) onSuccess, + required Function(dynamic response, int statusCode, {int? messageStatus, String? errorMessage}) onSuccess, required Function(String error, int statusCode, {int? messageStatus, Failure? failureType}) onFailure, bool isAllowAny, bool isExternal, @@ -77,29 +75,26 @@ abstract class ApiClient { class ApiClientImp implements ApiClient { final _analytics = getIt(); - - final LoggerService loggerService; - final AppState appState; - final DialogService dialogService; + final LoggerService _loggerService; + final AppState _appState; ApiClientImp({ - required this.loggerService, - required this.dialogService, - required this.appState, - }); + required LoggerService loggerService, + required AppState appState, + }) : _appState = appState, + _loggerService = loggerService; @override post( String endPoint, { required Map body, - required Function(dynamic response, int statusCode, {int? messageStatus}) onSuccess, + required Function(dynamic response, int statusCode, {int? messageStatus, String? errorMessage}) onSuccess, required Function(String error, int statusCode, {int? messageStatus, Failure? failureType}) onFailure, - bool isAllowAny = false, + bool isAllowAny = true, bool isExternal = false, bool isRCService = false, bool bypassConnectionCheck = false, }) async { - AppState appState = getIt.get(); String url; if (isExternal) { url = endPoint; @@ -111,39 +106,19 @@ class ApiClientImp implements ApiClient { } } try { - var user = appState.getAuthenticatedUser; + var user = _appState.getAuthenticatedUser; Map headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}; if (!isExternal) { - String? token = appState.appAuthToken; - String? languageID = (appState.postParamsObject?.languageID == 1 ? 'ar' : 'en'); - if (endPoint == ApiConsts.sendActivationCode) { - languageID = 'en'; - } + String? token = _appState.appAuthToken; + if (body.containsKey('SetupID')) { body['SetupID'] = body.containsKey('SetupID') ? body['SetupID'] ?? body[''] : SETUP_ID; } else {} - if (body.containsKey('LanguageID')) { - if (body['LanguageID'] != null) { - body['LanguageID'] = body['LanguageID'] == 'ar' - ? 1 - : body['LanguageID'] == 'en' - ? 2 - : body['LanguageID']; - } - } - if (body.containsKey('isDentalAllowedBackend')) { body['isDentalAllowedBackend'] = body.containsKey('isDentalAllowedBackend') ? body['isDentalAllowedBackend'] ?? IS_DENTAL_ALLOWED_BACKEND : IS_DENTAL_ALLOWED_BACKEND; } - //Todo: I have converted it to string - body['DeviceTypeID'] = Platform.isIOS - ? "1" - : await Utils.isGoogleServicesAvailable() - ? "2" - : "3"; - if (!body.containsKey('IsPublicRequest')) { // if (!body.containsKey('PatientType')) { if (user != null && user.patientType != null) { @@ -158,6 +133,7 @@ class ApiClientImp implements ApiClient { body['PatientType'] = PATIENT_TYPE_ID.toString(); } + // TODO : These should be from the appState if (user != null) { body['TokenID'] = body['TokenID'] ?? token; body['PatientID'] = body['PatientID'] ?? user.patientID; @@ -175,129 +151,134 @@ class ApiClientImp implements ApiClient { // request.languageID = (languageID == 'ar' ? 1 : 2); // request.patientOutSA = (request.zipCode == '966' || request.zipCode == '+966') ? 0 : 1; - // TODO : we will use all these from appState - body['LanguageID'] = body['LanguageID'] ?? "2"; - body['VersionID'] = body['VersionID'] ?? "50.0"; - body['Channel'] = body['Channel'] ?? "3"; - body['IPAdress'] = body['IPAdress'] ?? "10.20.10.20"; - body['generalid'] = body['generalid'] ?? "Cs2020@2016\$2958"; - body['Latitude'] = body['Latitude'] ?? "0.0"; - body['Longitude'] = body['Longitude'] ?? "0.0"; - body['DeviceTypeID'] = body['DeviceTypeID'] ?? - (Platform.isIOS - ? "1" - : await Utils.isGoogleServicesAvailable() - ? "2" - : "3"); - body['TokenID'] = "@dm!n"; + body['VersionID'] = ApiConsts.appVersionID.toString(); + body['Channel'] = ApiConsts.appChannelId.toString(); + body['IPAdress'] = ApiConsts.appIpAddress; + body['generalid'] = ApiConsts.appGeneralId; + + body['LanguageID'] = _appState.getLanguageID().toString(); + body['Latitude'] = _appState.userLat.toString(); + body['Longitude'] = _appState.userLong.toString(); + body['DeviceTypeID'] = _appState.deviceTypeID; + if (_appState.appLoginTokenID.isNotEmpty) { + body['LogInTokenID'] = _appState.appLoginTokenID; + } + body.removeWhere((key, value) => value == null); log("body: ${json.encode(body)}"); log("uri: ${Uri.parse(url.trim())}"); - if (await Utils.checkConnection(bypassConnectionCheck: bypassConnectionCheck)) { - final response = await http.post(Uri.parse(url.trim()), body: json.encode(body), headers: headers); + final bool networkStatus = await Utils.checkConnection(bypassConnectionCheck: bypassConnectionCheck); - final int statusCode = response.statusCode; - if (statusCode < 200 || statusCode >= 400) { - onFailure('Error While Fetching data', statusCode, failureType: StatusCodeFailure("Error While Fetching data")); - logApiEndpointError(endPoint, 'Error While Fetching data', statusCode); + if (!networkStatus) { + onFailure( + 'Please Check The Internet Connection 1', + -1, + failureType: ConnectivityFailure("Please Check The Internet Connection 1"), + ); + _analytics.errorTracking.log("internet_connectivity", error: "no internet available"); + return; + } + + final response = await http.post(Uri.parse(url.trim()), body: json.encode(body), headers: headers); + final int statusCode = response.statusCode; + log("response.body: ${response.body}"); + if (statusCode < 200 || statusCode >= 400) { + var parsed = json.decode(utf8.decode(response.bodyBytes)); + onFailure('Error While Fetching data', statusCode, failureType: StatusCodeFailure("Error While Fetching data")); + logApiEndpointError(endPoint, 'Error While Fetching data', statusCode); + } else { + var parsed = json.decode(utf8.decode(response.bodyBytes)); + if (isAllowAny) { + onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); } else { - var parsed = json.decode(utf8.decode(response.bodyBytes)); - log("parsed: ${parsed.toString()}"); - if (isAllowAny) { - onSuccess(parsed, statusCode); + if (parsed['Response_Message'] != null) { + onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); } else { - if (parsed['Response_Message'] != null) { - onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']); - } else { - if (parsed['ErrorType'] == 4) { - //TODO : handle app update + if (parsed['ErrorType'] == 4) { + //TODO : handle app update + logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); + } + if (parsed['ErrorType'] == 2) { + // todo: handle Logout + logApiEndpointError(endPoint, "session logged out", statusCode); + } + if (isAllowAny) { + onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); + } else if (parsed['IsAuthenticated'] == null) { + if (parsed['isSMSSent'] == true) { + onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); + } else if (parsed['MessageStatus'] == 1) { + onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); + } else if (parsed['Result'] == 'OK') { + onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); + } else { + onFailure( + parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], + statusCode, + failureType: MessageStatusFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']), + ); logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); } - if (parsed['ErrorType'] == 2) { - // todo: handle Logout - logApiEndpointError(endPoint, "session logged out", statusCode); - } - if (isAllowAny) { - onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']); - } else if (parsed['IsAuthenticated'] == null) { - if (parsed['isSMSSent'] == true) { - onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']); - } else if (parsed['MessageStatus'] == 1) { - onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']); - } else if (parsed['Result'] == 'OK') { - onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']); - } else { - onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode, failureType: ServerFailure("Error While Fetching data")); - logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); - } - } else if (parsed['MessageStatus'] == 1 || parsed['SMSLoginRequired'] == true) { - onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']); - } else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) { - if (parsed['SameClinicApptList'] != null) { - onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']); - } else { - if (parsed['message'] == null && parsed['ErrorEndUserMessage'] == null) { - if (parsed['ErrorSearchMsg'] == null) { - onFailure( - "Server Error found with no available message", - statusCode, - failureType: ServerFailure("Error While Fetching data"), - ); - logApiEndpointError(endPoint, "Server Error found with no available message", statusCode); - } else { - onFailure( - parsed['ErrorSearchMsg'], - statusCode, - failureType: ServerFailure("Error While Fetching data"), - ); - logApiEndpointError(endPoint, parsed['ErrorSearchMsg'], statusCode); - } - } else { - onFailure( - parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], - statusCode, - failureType: ServerFailure("Error While Fetching data"), - ); - logApiEndpointError(endPoint, parsed['message'] ?? parsed['message'], statusCode); - } - } + } else if (parsed['MessageStatus'] == 1 || parsed['SMSLoginRequired'] == true) { + onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); + } else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) { + if (parsed['SameClinicApptList'] != null) { + onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); } else { - if (parsed['SameClinicApptList'] != null) { - onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus']); - } else { - if (parsed['message'] != null) { + if (parsed['message'] == null && parsed['ErrorEndUserMessage'] == null) { + if (parsed['ErrorSearchMsg'] == null) { onFailure( - parsed['message'] ?? parsed['message'], + "Server Error found with no available message", statusCode, failureType: ServerFailure("Error While Fetching data"), ); - logApiEndpointError(endPoint, parsed['message'] ?? parsed['message'], statusCode); + logApiEndpointError(endPoint, "Server Error found with no available message", statusCode); } else { onFailure( - parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], + parsed['ErrorSearchMsg'], statusCode, failureType: ServerFailure("Error While Fetching data"), ); - logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); + logApiEndpointError(endPoint, parsed['ErrorSearchMsg'], statusCode); } + } else { + onFailure( + parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], + statusCode, + failureType: UserIntimationFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']), + ); + logApiEndpointError(endPoint, parsed['message'] ?? parsed['message'], statusCode); + } + } + } else { + if (parsed['SameClinicApptList'] != null) { + onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']); + } else { + if (parsed['message'] != null) { + onFailure( + parsed['message'] ?? parsed['message'], + statusCode, + failureType: ServerFailure("Error While Fetching data"), + ); + logApiEndpointError(endPoint, parsed['message'] ?? parsed['message'], statusCode); + } else { + onFailure( + parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], + statusCode, + failureType: ServerFailure("Error While Fetching data"), + ); + logApiEndpointError(endPoint, parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode); } } } } } - } else { - onFailure( - 'Please Check The Internet Connection 1', - -1, - failureType: ConnectivityFailure("Error While Fetching data"), - ); - _analytics.errorTracking.log("internet_connectivity", error: "no internet available"); } - } catch (e) { - loggerService.errorLogs(e.toString()); + } catch (e, stackTrace) { + _loggerService.errorLogs(stackTrace.toString()); if (e.toString().contains("ClientException")) { - onFailure('Something went wrong, plase try again', -1, failureType: InvalidCredentials('Something went wrong, plase try again')); + onFailure('ClientException: Something went wrong, Please try again', -1, failureType: InvalidCredentials('ClientException: Something went wrong, plase try again')); _analytics.errorTracking.log("internet_connectivity", error: "no internet available"); } else { onFailure(e.toString(), -1); diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart index 11c44ba..5a38342 100644 --- a/lib/core/api_consts.dart +++ b/lib/core/api_consts.dart @@ -1,4 +1,4 @@ -import 'dart:io'; +import 'package:hmg_patient_app_new/core/enums.dart'; var MAX_SMALL_SCREEN = 660; final OPENTOK_API_KEY = '46209962'; @@ -350,7 +350,6 @@ var CAN_PAY_FOR_FOR_WALKIN_APPOINTMENT = 'Services/Doctors.svc/REST/CanPayForWal var CHANNEL = 3; var GENERAL_ID = 'Cs2020@2016\$2958'; var IP_ADDRESS = '10.20.10.20'; -var VERSION_ID = 18.7; var SETUP_ID = '91877'; var LANGUAGE = 2; // var PATIENT_OUT_SA = 0; @@ -702,20 +701,12 @@ var applePayMerchantId = "merchant.com.hmgwebservices"; // var payFortEnvironment = FortEnvironment.test; // var applePayMerchantId = "merchant.com.hmgwebservices.uat"; - - // Auth Provider Consts - const String INSERT_DEVICE_IMEI = 'Services/Patients.svc/REST/Patient_INSERTDeviceIMEI'; const String SELECT_DEVICE_IMEI = 'Services/Patients.svc/REST/Patient_SELECTDeviceIMEIbyIMEI'; const String CHECK_PATIENT_AUTH = 'Services/Authentication.svc/REST/CheckPatientAuthentication'; const GET_MOBILE_INFO = 'Services/Authentication.svc/REST/GetMobileLoginInfo'; -const SEND_ACTIVATION_CODE = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationType'; - -const SEND_ACTIVATION_CODE_REGISTER = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationTypeForRegistration'; -const CHECK_ACTIVATION_CODE = 'Services/Authentication.svc/REST/CheckActivationCode'; -const CHECK_ACTIVATION_CODE_REGISTER = 'Services/Authentication.svc/REST/CheckActivationCodeForRegistration'; const FORGOT_PASSWORD = 'Services/Authentication.svc/REST/CheckActivationCodeForSendFileNo'; const CHECK_PATIENT_FOR_REGISTRATION = "Services/Authentication.svc/REST/CheckPatientForRegisteration"; @@ -731,34 +722,53 @@ const SAVE_SETTING = 'Services/Patients.svc/REST/UpdatePateintInfo'; const DEACTIVATE_ACCOUNT = 'Services/Patients.svc/REST/PatientAppleActivation_InsertUpdate'; - - class ApiConsts { static const maxSmallScreen = 660; - static bool isDevelopment = true; + static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.prod; // static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT + static String baseUrl = 'https://hmgwebservices.com/'; // HIS API URL PROD static String SELECT_DEVICE_IMEI = 'Services/Patients.svc/REST/Patient_SELECTDeviceIMEIbyIMEI'; static num VERSION_ID = 18.9; - static final String selectDeviceImei = 'Services/Patients.svc/REST/Patient_SELECTDeviceIMEIbyIMEI'; - static final String sendActivationCode = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationType'; - - static setBackendURLs() { - if (isDevelopment) { - baseUrl = "https://uat.hmgwebservices.com/"; - } else { - baseUrl = "https://hmgwebservices.com/"; + switch (appEnvironmentType) { + case AppEnvironmentTypeEnum.prod: + baseUrl = "https://hmgwebservices.com/"; + break; + case AppEnvironmentTypeEnum.dev: + baseUrl = "https://uat.hmgwebservices.com/"; + break; + case AppEnvironmentTypeEnum.uat: + baseUrl = "https://uat.hmgwebservices.com/"; + break; + case AppEnvironmentTypeEnum.preProd: + baseUrl = "https://webservices.hmg.com/"; + break; + case AppEnvironmentTypeEnum.qa: + baseUrl = "https://uat.hmgwebservices.com/"; + break; + case AppEnvironmentTypeEnum.staging: + baseUrl = "https://uat.hmgwebservices.com/"; + break; } } + static final String selectDeviceImei = 'Services/Patients.svc/REST/Patient_SELECTDeviceIMEIbyIMEI'; + static final String checkPatientAuth = 'Services/Authentication.svc/REST/CheckPatientAuthentication'; - - static final Map packagesAuthHeader = {}; - -} \ No newline at end of file + static final String sendActivationCode = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationType'; + static final String sendActivationCodeRegister = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationTypeForRegistration'; + static final String checkActivationCode = 'Services/Authentication.svc/REST/CheckActivationCode'; + static final String checkActivationCodeRegister = 'Services/Authentication.svc/REST/CheckActivationCodeForRegistration'; + + // static values for Api + static final double appVersionID = 18.7; + static final int appChannelId = 3; + static final String appIpAddress = "10.20.10.20"; + static final String appGeneralId = "Cs2020@2016\$2958"; +} diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart index 7f1b6d1..ac3cfe6 100644 --- a/lib/core/app_assets.dart +++ b/lib/core/app_assets.dart @@ -72,6 +72,9 @@ class AppAssets { static const String cancel_circle_icon = '$svgBasePath/cancel_circle.svg'; static const String update_insurance_card_icon = '$svgBasePath/update_insurance_card.svg'; static const String close_bottom_sheet_icon = '$svgBasePath/close_bottom_sheet_icon.svg'; + static const String insurance = '$svgBasePath/insurance.svg'; + static const String requests = '$svgBasePath/requests.svg'; + static const String more = '$svgBasePath/more.svg'; //bottom navigation// static const String homeBottom = '$svgBasePath/home_bottom.svg'; diff --git a/lib/core/app_state.dart b/lib/core/app_state.dart index eb9315c..008aeb8 100644 --- a/lib/core/app_state.dart +++ b/lib/core/app_state.dart @@ -1,59 +1,64 @@ import 'package:easy_localization/easy_localization.dart'; -import 'package:hmg_patient_app_new/core/post_params_model.dart'; import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart'; +import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; -import 'api_consts.dart' as ApiConsts; - class AppState { NavigationService navigationService; AppState({required this.navigationService}); - bool isAuthenticated = true; + double userLat = 0.0; - set setIsAuthenticated(v) => isAuthenticated = v; + set setUserLat(v) => userLat = v; - set setAppAuthToken(v) => appAuthToken = v; + double userLong = 0.0; - String appAuthToken = ""; + set setUserLong(v) => userLong = v; - set setUserLat(v) => userLat = v; + bool isArabic() => EasyLocalization.of(navigationService.navigatorKey.currentContext!)?.locale.languageCode == "ar"; - set setUserLong(v) => userLong = v; + int getLanguageID() => EasyLocalization.of(navigationService.navigatorKey.currentContext!)?.locale.languageCode == "ar" ? 1 : 2; - final PostParamsModel _postParamsInitConfig = - PostParamsModel(channel: 3, versionID: ApiConsts.VERSION_ID, ipAddress: '10.20.10.20', generalId: 'Cs2020@2016\$2958', deviceTypeID: "2", sessionID: 'TMRhVmkGhOsvamErw'); + String? getLanguageCode() => EasyLocalization.of(navigationService.navigatorKey.currentContext!)?.locale.languageCode; - void setPostParamsInitConfig() { - isAuthenticated = false; - _postParams = _postParamsInitConfig; - } + AuthenticatedUser? _authenticatedUser; - PostParamsModel? _postParams; + void setAuthenticatedUser(AuthenticatedUser authenticatedUser) { + _authenticatedUser = authenticatedUser; + } - PostParamsModel? get postParamsObject => _postParams; + AuthenticatedUser? get getAuthenticatedUser => _authenticatedUser; - Map get postParamsJson => isAuthenticated ? (_postParams?.toJsonAfterLogin() ?? {}) : (_postParams?.toJson() ?? {}); + SelectDeviceByImeiRespModelElement? _selectDeviceByImeiRespModelElement; - void setPostParamsModel(PostParamsModel _postParams) { - this._postParams = _postParams; + void setSelectDeviceByImeiRespModelElement(SelectDeviceByImeiRespModelElement value) { + _selectDeviceByImeiRespModelElement = value; } - double userLat = 0.0; - double userLong = 0.0; + SelectDeviceByImeiRespModelElement? get getSelectDeviceByImeiRespModelElement => _selectDeviceByImeiRespModelElement; - bool isArabic() => EasyLocalization.of(navigationService.navigatorKey.currentContext!)?.locale.languageCode == "ar"; + String appLoginTokenID = ""; - int getLanguageID() => EasyLocalization.of(navigationService.navigatorKey.currentContext!)?.locale.languageCode == "ar" ? 1 : 2; + set setAppLoginTokenID(v) => appLoginTokenID = v; - String? getLanguageCode() => EasyLocalization.of(navigationService.navigatorKey.currentContext!)?.locale.languageCode; + String deviceToken = ""; - AuthenticatedUser? _authenticatedUser; + set setDeviceToken(v) => deviceToken = v; - void setAuthenticatedUser(AuthenticatedUser authenticatedUser) { - _authenticatedUser = authenticatedUser; - } + String appAuthToken = ""; - AuthenticatedUser? get getAuthenticatedUser => _authenticatedUser; + set setAppAuthToken(v) => appAuthToken = v; + + String sessionId = ""; + + set setSessionId(v) => sessionId = v; + + bool isAuthenticated = true; + + set setIsAuthenticated(v) => isAuthenticated = v; + + String deviceTypeID = ""; + + set setDeviceTypeID(v) => deviceTypeID = v; } diff --git a/lib/core/cache_consts.dart b/lib/core/cache_consts.dart new file mode 100644 index 0000000..b793f02 --- /dev/null +++ b/lib/core/cache_consts.dart @@ -0,0 +1,75 @@ +class CacheConst { + static const String isRememberMe = "remember_me"; + static const String username = "doctorId"; + static const String password = "password"; + static const String logInTokenId = "logInTokenID"; + static const String vidaAuthTokenId = "vidaAuthTokenID"; + static const String vidaRefreshTokenId = "vidaRefreshTokenID"; + static const String authenticationTokenId = "authenticationTokenID"; + static const String projectId = "projectID"; + static const String clinicId = "clinicId"; + static const String lastLoginDate = "lastLoginDate"; + static const String lastLoginTime = "lastLoginTime"; + static const String memberModel = "memberModel"; + + static const String isShowOnboarding = "is_show_onboarding"; + static const String appAuthToken = "app_auth_token"; + static const String appUserId = "app_user_id"; + static const String loggedInUserObj = "logged_in_user_obj"; + + static const String pushToken = "push_token"; + static const String apnsToken = "apns_token"; + static const String voipToken = "voip_token"; + static const String patientMrn = "patient_mrn"; + + static const String loggedInUserId = "logged_in_user_id"; + static const String loggedInUserPassword = "logged_in_user_password"; + + static const String userLat = 'user-lat'; + static const String userLong = 'user-long'; + + static const String token = 'token'; + static const String appLanguage = 'language'; + static const String userProfile = 'user-profile'; + static const String oneSignalApnsToken = 'onesignal-apns-token'; + static const String registerDataForRegister = 'register-data-for-register'; + static const String loginTokenIdDuplicate = 'register-data-for-register'; + static const String registerDataForLogin = 'register-data-for-login'; + static const String lastLogin = 'last-login'; + static const String erCheckinRiskScore = 'er-checkin-risk-score'; + static const String onlySms = 'only-sms'; + static const String authData = 'auth-data'; + static const String imeiUserData = 'imei-user-data'; + static const String nhicData = 'nhic-data'; + static const String familyFile = 'family-file'; + static const String isGoToParking = 'IS_GO_TO_PARKING'; + static const String isSearchAppo = 'is-search-appo'; + static const String isLivecareAppointment = 'is_livecare_appointment'; + static const String isVibration = 'is_vibration'; + static const String themeValue = 'is_vibration'; + static const String mainUser = 'main-user'; + static const String pharmacyLastVisitedProducts = 'last-visited'; + static const String pharmacyCustomerId = 'costumer-id'; + static const String pharmacyCustomerGuid = 'customer-guid'; + static const String pharmacyCustomerObject = 'pharmacy-customer-object'; + static const String isRobotVisible = 'robot-visible'; + static const String isRobotInit = 'robot-init'; + static const String hmgGeofences = 'hmg-geo-fences'; + static const String weather = 'weather'; + static const String bloodType = 'blood-type'; + static const String notificationCount = 'notification-count'; + static const String pharmacySelectedAddress = 'selected-address'; + static const String pharmacyAutorzieToken = 'PHARMACY_AUTORZIE_TOKEN'; + static const String h2oUnit = 'H2O_UNIT'; + static const String h2oReminder = 'H2O_REMINDER'; + static const String livecareClinicData = 'LIVECARE_CLINIC_DATA'; + static const String doctorScheduleDateSel = 'DOCTOR_SCHEDULE_DATE_SEL'; + static const String appointmentHistoryMedical = 'APPOINTMENT_HISTORY_MEDICAL'; + static const String clinicsList = 'CLINICS_LIST'; + static const String covidQaList = 'COVID_QA_LIST'; + static const String isCovidConsentShown = 'IS_COVID_CONSENT_SHOWN'; + static const String registerInfoDubai = 'register-info-dubai'; + static const String isLastAppointmentRateShown = 'is-last-appointment-rate-shown'; + static const String patientOccupationList = 'patient-occupation-list'; + static const String hasEnabledQuickLogin = 'has-enabled-quick-login'; +} diff --git a/lib/core/consts.dart b/lib/core/consts.dart deleted file mode 100644 index 216b9a7..0000000 --- a/lib/core/consts.dart +++ /dev/null @@ -1,32 +0,0 @@ - - -class SharedPrefsConsts { - static String isRememberMe = "remember_me"; - static String username = "doctorId"; - static String password = "password"; - static String logInTokenID = "logInTokenID"; - static String vidaAuthTokenID = "vidaAuthTokenID"; - static String vidaRefreshTokenID = "vidaRefreshTokenID"; - static String authenticationTokenID = "authenticationTokenID"; - static String projectID = "projectID"; - static String clinicId = "clinicId"; - static String lastLoginDate = "lastLoginDate"; - static String lastLoginTime = "lastLoginTime"; - static String memberModel = "memberModel"; - - static String isShowOnboarding = "is_show_onboarding"; - static String appAuthToken = "app_auth_token"; - static String appUserID = "app_user_id"; - static String loggedInUserObj = "logged_in_user_obj"; - - static String PUSH_TOKEN = "push_token"; - static String APNS_TOKEN = "apns_token"; - static String VOIP_TOKEN = "voip_token"; - static String PATIENT_MRN = "patient_mrn"; - - static String loggedInUserID = "logged_in_user_id"; - static String loggedInUserPassword = "logged_in_user_password"; - - static String user_lat = 'user-lat'; - static String user_long = 'user-long'; -} diff --git a/lib/core/dependencies.dart b/lib/core/dependencies.dart index aa32fa6..a900742 100644 --- a/lib/core/dependencies.dart +++ b/lib/core/dependencies.dart @@ -1,3 +1,4 @@ +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:get_it/get_it.dart'; import 'package:hmg_patient_app_new/core/api/api_client.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; @@ -19,6 +20,7 @@ import 'package:hmg_patient_app_new/services/analytics/analytics_service.dart'; import 'package:hmg_patient_app_new/services/cache_service.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/firebase_service.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:logger/web.dart'; @@ -32,7 +34,7 @@ class AppDependencies { printer: PrettyPrinter( methodCount: 2, errorMethodCount: 5, - lineLength: 100, + lineLength: 1000, colors: true, printEmojis: true, ), @@ -40,6 +42,12 @@ class AppDependencies { // Core Services getIt.registerLazySingleton(() => LoggerServiceImp(logger: logger)); + getIt.registerLazySingleton(() => FirebaseServiceImpl( + loggerService: getIt(), + appState: getIt(), + firebaseMessaging: FirebaseMessaging.instance, + )); + getIt.registerLazySingleton(() => NavigationService()); getIt.registerLazySingleton(() => GAnalytics()); getIt.registerLazySingleton(() => AppState(navigationService: getIt())); @@ -56,8 +64,8 @@ class AppDependencies { )); final sharedPreferences = await SharedPreferences.getInstance(); - getIt.registerLazySingleton(() => CacheServiceImp(sharedPreferences: sharedPreferences)); - getIt.registerLazySingleton(() => ApiClientImp(loggerService: getIt(), dialogService: getIt(), appState: getIt())); + getIt.registerLazySingleton(() => CacheServiceImp(sharedPreferences: sharedPreferences, loggerService: getIt())); + getIt.registerLazySingleton(() => ApiClientImp(loggerService: getIt(), appState: getIt())); // Repositories getIt.registerLazySingleton(() => CommonRepoImp(loggerService: getIt())); @@ -103,6 +111,8 @@ class AppDependencies { getIt.registerLazySingleton( () => AuthenticationViewModel( authenticationRepo: getIt(), + cacheService: getIt(), + navigationService: getIt(), dialogService: getIt(), appState: getIt(), errorHandlerService: getIt(), diff --git a/lib/core/enums.dart b/lib/core/enums.dart index 34aa911..ab5cac1 100644 --- a/lib/core/enums.dart +++ b/lib/core/enums.dart @@ -22,8 +22,6 @@ enum ViewStateEnum { errorLocal, } -enum OTPTypeEnum { sms, whatsapp } - enum CountryEnum { saudiArabia, unitedArabEmirates } enum SelectionTypeEnum { dropdown, calendar } @@ -34,8 +32,12 @@ enum MaritalStatusTypeEnum { single, married, divorced, widowed } enum ChipTypeEnum { success, error, alert, info, warning } +enum OTPTypeEnum { sms, whatsapp } + enum LoginTypeEnum { sms, whatsapp, face, fingerprint } +enum AppEnvironmentTypeEnum { dev, uat, preProd, qa, staging, prod } + extension LoginTypeExtension on LoginTypeEnum { int get toInt { switch (this) { diff --git a/lib/core/exceptions/api_failure.dart b/lib/core/exceptions/api_failure.dart index 4bc5097..c950195 100644 --- a/lib/core/exceptions/api_failure.dart +++ b/lib/core/exceptions/api_failure.dart @@ -13,6 +13,20 @@ class ServerFailure extends Failure { List get props => [message]; } +class UserIntimationFailure extends Failure { + const UserIntimationFailure(super.message); + + @override + List get props => [message]; +} + +class MessageStatusFailure extends Failure { + const MessageStatusFailure(super.message); + + @override + List get props => [message]; +} + class StatusCodeFailure extends Failure { const StatusCodeFailure(super.message); @@ -48,7 +62,6 @@ class UnknownFailure extends Failure { List get props => [message]; } - class DuplicateUsername extends Failure { const DuplicateUsername(String? message) : super(message ?? ''); @@ -62,5 +75,3 @@ class InvalidCredentials extends Failure { @override List get props => [message]; } - - diff --git a/lib/core/location_util.dart b/lib/core/location_util.dart index dc6a0d6..d556034 100644 --- a/lib/core/location_util.dart +++ b/lib/core/location_util.dart @@ -3,7 +3,7 @@ import 'dart:io'; import 'package:geolocator/geolocator.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; -import 'package:hmg_patient_app_new/core/consts.dart'; +import 'package:hmg_patient_app_new/core/cache_consts.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:permission_handler/permission_handler.dart'; @@ -143,8 +143,8 @@ class LocationUtils { } void setLocation(Position? position) { - Utils.saveNumFromPrefs(SharedPrefsConsts.user_lat, position?.latitude ?? 0.0); - Utils.saveNumFromPrefs(SharedPrefsConsts.user_lat, position?.longitude ?? 0.0); + Utils.saveNumFromPrefs(CacheConst.userLat, position?.latitude ?? 0.0); + Utils.saveNumFromPrefs(CacheConst.userLong, position?.longitude ?? 0.0); appState.setUserLat = position?.latitude ?? 0.0; appState.setUserLong = position?.longitude ?? 0.0; @@ -153,8 +153,8 @@ class LocationUtils { } void setZeroLocation() { - Utils.saveNumFromPrefs(SharedPrefsConsts.user_lat, 0.0); - Utils.saveNumFromPrefs(SharedPrefsConsts.user_lat, 0.0); + Utils.saveNumFromPrefs(CacheConst.userLat, 0.0); + Utils.saveNumFromPrefs(CacheConst.userLong, 0.0); appState.setUserLat = 0.0; appState.setUserLong = 0.0; diff --git a/lib/core/post_params_model.dart b/lib/core/post_params_model.dart index 2f981f6..cf52306 100644 --- a/lib/core/post_params_model.dart +++ b/lib/core/post_params_model.dart @@ -14,7 +14,19 @@ class PostParamsModel { String? sessionID; String? setupID; - PostParamsModel({this.versionID, this.channel, this.languageID, this.logInTokenID, this.tokenID, this.language, this.ipAddress, this.generalId, this.latitude, this.longitude, this.deviceTypeID, this.sessionID}); + PostParamsModel( + {this.versionID, + this.channel, + this.languageID, + this.logInTokenID, + this.tokenID, + this.language, + this.ipAddress, + this.generalId, + this.latitude, + this.longitude, + this.deviceTypeID, + this.sessionID}); PostParamsModel.fromJson(Map json) { versionID = json['VersionID']; diff --git a/lib/core/utils/calendar_utils.dart b/lib/core/utils/calendar_utils.dart index 8786f7f..54b550f 100644 --- a/lib/core/utils/calendar_utils.dart +++ b/lib/core/utils/calendar_utils.dart @@ -4,7 +4,12 @@ import 'dart:io'; import 'dart:ui'; import 'package:device_calendar/device_calendar.dart'; +import 'package:flutter/widgets.dart'; +import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; +import 'package:hmg_patient_app_new/services/permission_service.dart'; +import 'package:jiffy/jiffy.dart'; import 'package:manage_calendar_events/manage_calendar_events.dart' as ios; +import 'package:permission_handler/permission_handler.dart'; import 'package:timezone/data/latest.dart' as tzl; final DeviceCalendarPlugin deviceCalendarPlugin = DeviceCalendarPlugin(); @@ -44,6 +49,94 @@ class CalendarUtils { // return _completer!.future; // } + Future> requestPermissions() async { + var permissionResults = [Permission.calendarFullAccess].request(); + return permissionResults; + } + + // showReminderDialog(BuildContext context, DateTime dateTime, String doctorName, String eventId, String appoDateFormatted, String appoTimeFormatted, + // {required Function() onSuccess, String? title, String? description, Function(int)? onMultiDateSuccess, bool isMultiAllowed = false}) async { + // if (Platform.isAndroid) { + // if (await PermissionService.isCalendarPermissionEnabled()) { + // _showReminderDialog(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted, + // onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed); + // } else { + // // Utils.showPermissionConsentDialog(context, TranslationBase.of(context).calendarPermission, () async { + // // if (await Permission.calendarFullAccess.request().isGranted) { + // // _showReminderDialog(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted, + // // onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed); + // // } + // // }); + // } + // } else { + // if (await Permission.calendarWriteOnly.request().isGranted) { + // if (await Permission.calendarFullAccess.request().isGranted) { + // _showReminderDialog(context, dateTime, doctorName, eventId, appoDateFormatted, appoTimeFormatted, + // onSuccess: onSuccess, title: title, description: description, onMultiDateSuccess: onMultiDateSuccess, isMultiAllowed: isMultiAllowed); + // } + // } + // } + // } + + // Future _showReminderDialog(BuildContext providedContext, DateTime dateTime, String doctorName, String eventId, String appoDateFormatted, String appoTimeFormatted, + // {required Function onSuccess, String? title, String? description, Function(int)? onMultiDateSuccess, bool? isMultiAllowed}) async { + // return showDialog( + // context: providedContext, + // barrierDismissible: true, // user must tap button! + // builder: (BuildContext context) { + // return Dialog( + // shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0.0)), + // insetPadding: EdgeInsets.all(21), + // child: ReminderDialog( + // onClick: (int i) async { + // String text = ""; + // if (i == 0) { + // // Before 30 mints + // dateTime = Jiffy.parseFromDateTime(dateTime).subtract(minutes: 30).dateTime; + // text = "30 minutes"; + // // dateTime.add(new Duration(minutes: -30)); + // } else if (i == 1) { + // // Before 1 hour + // // dateTime.add(new Duration(minutes: -60)); + // dateTime = Jiffy.parseFromDateTime(dateTime).subtract(hours: 1).dateTime; + // text = "1 hours"; + // } else if (i == 2) { + // // Before 1 hour and 30 mints + // // dateTime.add(new Duration(minutes: -90)); + // dateTime = Jiffy.parseFromDateTime(dateTime).subtract(hours: 1, minutes: 30).dateTime; + // text = "1 hours 30 minutes"; + // } else if (i == 3) { + // // Before 2 hours + // // dateTime.add(new Duration(minutes: -120)); + // dateTime = Jiffy.parseFromDateTime(dateTime).subtract(hours: 2).dateTime; + // text = "2 hours"; + // } + // if (!isMultiAllowed!) { + // if (onMultiDateSuccess == null) { + // CalendarUtils calendarUtils = await CalendarUtils.getInstance(); + // await calendarUtils.createOrUpdateEvent( + // title: title ?? "TranslationBase.of(providedContext).reminderTitle".needTranslation + " " + doctorName, + // description: description ?? "At " + appoDateFormatted + " " + appoTimeFormatted, + // scheduleDateTime: dateTime, + // eventId: eventId, location: ''); + // onSuccess(); + // } + // } else { + // onMultiDateSuccess!(i); + // } + // // await _analytics.logEvent( + // // name: name.trim().toLowerCase(), + // // parameters: safeParameters, + // // ); + // // todo @sikander discuss analytics for reminder + // // locator().appointment.appointment_reminder_time(reminde_before: text); + // }, + // ), + // ); + // }, + // ); + // } + static Future getInstance() async { tzl.initializeTimeZones(); if (_completer != null) { diff --git a/lib/core/utils/loading_utils.dart b/lib/core/utils/loading_utils.dart new file mode 100644 index 0000000..16555e8 --- /dev/null +++ b/lib/core/utils/loading_utils.dart @@ -0,0 +1,48 @@ +import 'dart:developer'; + +import 'package:flutter/material.dart'; +import 'package:hmg_patient_app_new/core/dependencies.dart'; +import 'package:hmg_patient_app_new/services/navigation_service.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart'; + +class LoadingUtils { + static final NavigationService _navigationService = getIt.get(); + + static bool _isLoadingVisible = false; + + static bool get isLoading => _isLoadingVisible; + + static showFullScreenLoader({bool barrierDismissible = true}) { + if (!_isLoadingVisible) { + _isLoadingVisible = true; + final context = _navigationService.navigatorKey.currentContext; + log("got the context in showFullScreenLoading"); + if (context == null) return; + + showDialog( + barrierDismissible: barrierDismissible, + context: context, + barrierColor: AppColors.blackColor.withOpacity(0.5), + useRootNavigator: false, + builder: (BuildContext context) => Center( + child: CircularProgressIndicator( + color: AppColors.primaryRedColor, + )), + ).then((value) { + _isLoadingVisible = false; + }); + } + } + + static hideFullScreenLoader() { + if (!_isLoadingVisible) return; + + final context = _navigationService.navigatorKey.currentContext; + if (context != null) { + try { + Navigator.of(context).pop(); + } catch (_) {} + } + _isLoadingVisible = false; + } +} diff --git a/lib/core/utils/push_notification_handler.dart b/lib/core/utils/push_notification_handler.dart index b5a816e..1d2141e 100644 --- a/lib/core/utils/push_notification_handler.dart +++ b/lib/core/utils/push_notification_handler.dart @@ -15,7 +15,7 @@ import 'package:hmg_patient_app_new/core/utils/local_notifications.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:permission_handler/permission_handler.dart'; -import '../consts.dart'; +import '../cache_consts.dart'; // |--> Push Notification Background @pragma('vm:entry-point') @@ -256,7 +256,7 @@ class PushNotificationHandler { final permission = await FirebaseMessaging.instance.requestPermission(); await FirebaseMessaging.instance.getAPNSToken().then((value) async { log("APNS token: " + value.toString()); - await Utils.saveStringFromPrefs(SharedPrefsConsts.APNS_TOKEN, value.toString()); + await Utils.saveStringFromPrefs(CacheConst.apnsToken, value.toString()); }); await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions( alert: true, // Required to display a heads up notification @@ -269,11 +269,11 @@ class PushNotificationHandler { try { FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage? message) async { if (message != null) { - if (Platform.isIOS) + if (Platform.isIOS) { await Future.delayed(Duration(milliseconds: 3000)).then((value) { if (message != null) newMessage(message); }); - else if (message != null) newMessage(message); + } else if (message != null) newMessage(message); } }); } catch (ex) {} @@ -281,22 +281,24 @@ class PushNotificationHandler { FirebaseMessaging.onMessage.listen((RemoteMessage message) async { print("Firebase onMessage!!!"); // showCallkitIncoming(); - if (Platform.isIOS) + if (Platform.isIOS) { await Future.delayed(Duration(milliseconds: 3000)).then((value) { newMessage(message); }); - else + } else { newMessage(message); + } }); FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async { print("Firebase onMessageOpenedApp!!!"); - if (Platform.isIOS) + if (Platform.isIOS) { await Future.delayed(Duration(milliseconds: 3000)).then((value) { newMessage(message); }); - else + } else { newMessage(message); + } }); FirebaseMessaging.instance.getToken().then((String? token) { @@ -350,7 +352,7 @@ class PushNotificationHandler { onToken(String token) async { print("Push Notification Token: " + token); - await Utils.saveStringFromPrefs(SharedPrefsConsts.PUSH_TOKEN, token); + await Utils.saveStringFromPrefs(CacheConst.pushToken, token); } onResume() async { @@ -363,9 +365,7 @@ class PushNotificationHandler { Future requestPermissions() async { try { if (Platform.isIOS) { - await flutterLocalNotificationsPlugin - .resolvePlatformSpecificImplementation() - ?.requestPermissions(alert: true, badge: true, sound: true); + await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation()?.requestPermissions(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 1869923..e83dd46 100644 --- a/lib/core/utils/request_utils.dart +++ b/lib/core/utils/request_utils.dart @@ -2,6 +2,47 @@ import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/features/authentication/models/request_models/send_activation_request_model.dart'; class RequestUtils { + static dynamic getPatientAuthenticationRequest({ + required String phoneNumber, + required String nationId, + required OTPTypeEnum otpTypeEnum, + required bool patientOutSA, + required bool isForRegister, + required int? patientId, + required String zipCode, + }) { + bool fileNo = false; + if (nationId.isNotEmpty) { + fileNo = nationId.length < 10; + } + var request = SendActivationRequest(); + if (phoneNumber.isNotEmpty) { + request.patientMobileNumber = int.parse(phoneNumber); + } + request.oTPSendType = otpTypeEnum.toInt(); // could map OTPTypeEnum if needed + request.zipCode = zipCode; // or countryCode if defined elsewhere + + if (isForRegister) { + // request.searchType = registeredData.searchType ?? 1; + // request.patientID = registeredData.patientID ?? 0; + // request.patientIdentificationID = request.nationalID = registeredData.patientIdentificationID ?? '0'; + // request.dob = registeredData.dob; + // request.isRegister = registeredData.isRegister; + } else { + if (fileNo) { + request.patientID = patientId ?? int.parse(nationId); + request.patientIdentificationID = request.nationalID = ""; + request.searchType = 2; + } else { + request.patientID = 0; + request.searchType = 1; + request.patientIdentificationID = request.nationalID = nationId.isNotEmpty ? nationId : '0'; + } + request.isRegister = false; + } + return request; + } + static dynamic getCommonRequestWelcome({ required String phoneNumber, required OTPTypeEnum otpTypeEnum, @@ -50,39 +91,38 @@ class RequestUtils { return request; } - static getCommonRequestAuthProvider({ + static getCommonRequestSendActivationCode({ required OTPTypeEnum otpTypeEnum, - required registeredData, - required deviceToken, - required mobileNumber, - required zipCode, - required patientOutSA, - required loginTokenID, - required selectedOption, + required String mobileNumber, + required String zipCode, required int? patientId, + required String? nationalId, + required bool patientOutSA, + required int selectedLoginType, + required bool isForRegister, + required bool isFileNo, }) { var request = SendActivationRequest(); - request.patientMobileNumber = mobileNumber; + if (mobileNumber.isNotEmpty) { + request.patientMobileNumber = int.parse(mobileNumber); + } request.mobileNo = '0$mobileNumber'; - request.deviceToken = deviceToken; - request.projectOutSA = patientOutSA == true ? true : false; - request.loginType = selectedOption; + request.projectOutSA = patientOutSA; + request.loginType = selectedLoginType; request.oTPSendType = otpTypeEnum.toInt(); //this.selectedOption == 1 ? 1 : 2; request.zipCode = zipCode; - request.logInTokenID = loginTokenID ?? ""; - - if (registeredData != null) { - request.searchType = registeredData.searchType ?? 1; - request.patientID = registeredData.patientID ?? 0; - request.patientIdentificationID = request.nationalID = registeredData.patientIdentificationID ?? '0'; - request.dob = registeredData.dob; - request.isRegister = registeredData.isRegister; + if (isForRegister) { + // request.searchType = registeredData.searchType ?? 1; + // request.patientID = registeredData.patientID ?? 0; + // request.patientIdentificationID = request.nationalID = registeredData.patientIdentificationID ?? '0'; + // request.dob = registeredData.dob; + // request.isRegister = registeredData.isRegister; } else { - request.searchType = request.searchType ?? 2; + request.searchType = isFileNo ? 2 : 1; request.patientID = patientId ?? 0; - request.nationalID = request.nationalID ?? '0'; - request.patientIdentificationID = request.patientIdentificationID ?? '0'; + request.nationalID = nationalId ?? '0'; + request.patientIdentificationID = nationalId ?? '0'; request.isRegister = false; } request.deviceTypeID = request.searchType; diff --git a/lib/core/utils/size_config.dart b/lib/core/utils/size_config.dart index 9c09b09..9f9d835 100644 --- a/lib/core/utils/size_config.dart +++ b/lib/core/utils/size_config.dart @@ -1,6 +1,6 @@ import 'package:flutter/cupertino.dart'; import 'package:hmg_patient_app_new/core/api_consts.dart'; -import 'package:hmg_patient_app_new/core/consts.dart'; +import 'package:hmg_patient_app_new/core/cache_consts.dart'; class SizeConfig { static double _blockWidth = 0; diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart index ed4770d..b539630 100644 --- a/lib/core/utils/utils.dart +++ b/lib/core/utils/utils.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:developer'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:crypto/crypto.dart' as crypto; @@ -13,7 +14,6 @@ import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; -import 'package:hmg_patient_app_new/services/dialog_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/dialogs/confirm_dialog.dart'; @@ -59,14 +59,12 @@ class Utils { // ), // )); return !isAddHours - ? DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US") - .format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.toLocal()) - : DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US") - .format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.add( - Duration( - hours: isAddHours ? 3 : 0, - ), - )); + ? DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US").format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.toLocal()) + : DateFormat('hh:mm a', appState.isArabic() ? "ar_SA" : "en_US").format(DateTime.tryParse(startTime.contains("T") ? startTime : convertStringToDateTime(startTime))!.add( + Duration( + hours: isAddHours ? 3 : 0, + ), + )); } static String convertStringToDateTime(String dateTimeString) { @@ -205,16 +203,16 @@ class Utils { _isLoadingVisible = true; showDialog( context: navigationService.navigatorKey.currentContext!, - barrierColor: Colors.black.withOpacity(0.5), + barrierColor: AppColors.blackColor, builder: (BuildContext context) => LoadingDialog(), ) .then((value) { - _isLoadingVisible = false; - }) + _isLoadingVisible = false; + }) .catchError((e) {}) .onError( (error, stackTrace) {}, - ); + ); } static void hideLoading() { @@ -224,7 +222,9 @@ class Utils { Navigator.of(navigationService.navigatorKey.currentContext!).pop(); } _isLoadingVisible = false; - } catch (e) {} + } catch (e) { + log("errr: ${e.toString()}"); + } } static List uniqueBy(List list, K Function(T) keySelector) { @@ -236,12 +236,11 @@ class Utils { showDialog( barrierDismissible: false, context: context, - builder: (cxt) => - ConfirmDialog( - title: title!, - message: message!, - onTap: onTap, - ), + builder: (cxt) => ConfirmDialog( + title: title!, + message: message!, + onTap: onTap, + ), ); } @@ -268,7 +267,7 @@ class Utils { var x = int.parse(a) * 2; var b = x.toString(); if (b.length == 1) { - b = "0" + b; + b = "0$b"; } sum += int.parse(b[0]) + int.parse(b[1]); } else { @@ -277,7 +276,9 @@ class Utils { } return sum % 10 == 0; } - } catch (err) {} + } catch (err) { + log("errr: ${err.toString()}"); + } return false; } else { return true; @@ -311,10 +312,8 @@ class Utils { } // Replace HTML line breaks with newlines - var withLineBreaks = htmlString - .replaceAll(RegExp(r'', multiLine: true), '\n') - .replaceAll(RegExp(r'<\/p>', multiLine: true), '\n') - .replaceAll(RegExp(r'', multiLine: true), '\n'); + var withLineBreaks = + htmlString.replaceAll(RegExp(r'', multiLine: true), '\n').replaceAll(RegExp(r'<\/p>', multiLine: true), '\n').replaceAll(RegExp(r'', multiLine: true), '\n'); // Remove all other HTML tags var withoutTags = withLineBreaks.replaceAll(RegExp(r'<[^>]*>'), ''); @@ -362,9 +361,8 @@ class Utils { final month = monthNames[dateTime.month - 1]; return '$day $month, $year'; - return '$day $month, $year'; } catch (e) { - print("Error formatting date: $e"); + log("Error formatting date: $e"); return ""; } } @@ -372,9 +370,7 @@ class Utils { static String formatHijriDateToDisplay(String hijriDateString) { try { // Assuming hijriDateString is in the format yyyy-MM-dd - final datePart = hijriDateString - .split("T") - .first; + final datePart = hijriDateString.split("T").first; final parts = datePart.split('-'); if (parts.length != 3) return ""; @@ -382,26 +378,13 @@ class Utils { final year = parts[0]; // Map month number to short month name (Hijri months) - const hijriMonthNames = [ - 'Muharram', - 'Safar', - 'Rabi I', - 'Rabi II', - 'Jumada I', - 'Jumada II', - 'Rajab', - 'Sha\'ban', - 'Ramadan', - 'Shawwal', - 'Dhu al-Qi\'dah', - 'Dhu al-Hijjah' - ]; + const hijriMonthNames = ['Muharram', 'Safar', 'Rabi I', 'Rabi II', 'Jumada I', 'Jumada II', 'Rajab', 'Sha\'ban', 'Ramadan', 'Shawwal', 'Dhu al-Qi\'dah', 'Dhu al-Hijjah']; final monthIndex = int.tryParse(parts[1]) ?? 1; final month = hijriMonthNames[monthIndex - 1]; return '$day $month, $year'; } catch (e) { - print("Error formatting hijri date: $e"); + log("Error formatting hijri date: $e"); return ""; } } @@ -415,7 +398,7 @@ class Utils { return '$day-$month-$year'; } catch (e) { - print("Error formatting date: $e"); + log("Error formatting date: $e"); return ""; } } @@ -432,14 +415,8 @@ class Utils { void Function(LottieComposition)? onLoaded, }) { return Lottie.asset(assetPath, - height: height ?? MediaQuery - .of(context) - .size - .height * 0.26, - width: width ?? MediaQuery - .of(context) - .size - .width, + height: height ?? MediaQuery.of(context).size.height * 0.26, + width: width ?? MediaQuery.of(context).size.width, fit: fit, alignment: alignment, repeat: repeat, @@ -499,10 +476,7 @@ class Utils { static Future isGoogleServicesAvailable() async { GooglePlayServicesAvailability availability = await GoogleApiAvailability.instance.checkGooglePlayServicesAvailability(); - String status = availability - .toString() - .split('.') - .last; + String status = availability.toString().split('.').last; if (status == "success") { return true; } @@ -523,26 +497,3 @@ class Utils { return crypto.md5.convert(utf8.encode(input)).toString(); } } - -class ValidationUtils { - static DialogService dialogService = getIt.get(); - - - static bool isValidatePhoneAndId({ - String? nationalId, - String? phoneNumber - }) { - if (nationalId == null || nationalId.isEmpty) { - dialogService.showErrorDialog(message: "Please enter a valid national ID or file number", onOkPressed: () {}); - return false; - } - - if (phoneNumber == null || phoneNumber.isEmpty) { - dialogService.showErrorDialog(message: "Please enter a valid phone number", onOkPressed: () {}); - return false; - } - return true; - } -} - - diff --git a/lib/core/utils/validation_utils.dart b/lib/core/utils/validation_utils.dart new file mode 100644 index 0000000..cb54af5 --- /dev/null +++ b/lib/core/utils/validation_utils.dart @@ -0,0 +1,23 @@ +import 'dart:developer'; + +import 'package:hmg_patient_app_new/core/dependencies.dart'; +import 'package:hmg_patient_app_new/services/dialog_service.dart'; + +class ValidationUtils { + static final DialogService _dialogService = getIt.get(); + + static bool isValidatePhoneAndId({String? nationalId, String? phoneNumber}) { + log("phoneNumber: $phoneNumber"); + log("nationalId: $nationalId"); + if (nationalId == null || nationalId.isEmpty) { + _dialogService.showErrorBottomSheet(message: "Please enter a valid national ID or file number", onOkPressed: () {}); + return false; + } + + if (phoneNumber == null || phoneNumber.isEmpty) { + _dialogService.showErrorBottomSheet(message: "Please enter a valid phone number", onOkPressed: () {}); + return false; + } + return true; + } +} diff --git a/lib/extensions/route_extensions.dart b/lib/extensions/route_extensions.dart index 71f5d2d..0dcc54b 100644 --- a/lib/extensions/route_extensions.dart +++ b/lib/extensions/route_extensions.dart @@ -20,4 +20,8 @@ extension NavigationExtensions on BuildContext { void navigateTo(Widget page) { Navigator.push(this, MaterialPageRoute(builder: (context) => page)); } + + void popUntilNamed(String routeName) { + Navigator.popUntil(this, ModalRoute.withName(routeName)); + } } diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 352415b..0f04824 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -13,6 +13,8 @@ extension CapExtension on String { String get allInCaps => this.toUpperCase(); + String get needTranslation => this; + String get capitalizeFirstofEach => this.trim().length > 0 ? this.trim().toLowerCase().split(" ").map((str) => str.inCaps).join(" ") : ""; } @@ -28,7 +30,7 @@ extension EmailValidator on String { fontStyle: fontStyle ?? FontStyle.normal, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, color: color ?? AppColors.blackColor, - letterSpacing: -0.4, + letterSpacing: -1, ), ); @@ -41,7 +43,7 @@ extension EmailValidator on String { fontStyle: fontStyle ?? FontStyle.normal, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, color: color ?? AppColors.blackColor, - letterSpacing: -0.4, + letterSpacing: -1, decoration: isUnderLine ? TextDecoration.underline : null, decorationColor: color ?? AppColors.blackColor), ); @@ -55,7 +57,7 @@ extension EmailValidator on String { fontSize: 11.fSize, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), color: color ?? AppColors.blackColor, - letterSpacing: -0.4, + letterSpacing: -1, decoration: isUnderLine ? TextDecoration.underline : null, ), ); @@ -68,7 +70,7 @@ extension EmailValidator on String { fontSize: 12.fSize, fontWeight: fontWeight ?? (isBold ? FontWeight.bold : FontWeight.normal), color: color ?? AppColors.blackColor, - letterSpacing: -0.4, + letterSpacing: -1, height: height, decorationColor: isUnderLine ? AppColors.blackColor : null, decoration: isUnderLine ? TextDecoration.underline : null, @@ -84,7 +86,7 @@ extension EmailValidator on String { fontSize: 12.fSize, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, color: color ?? AppColors.blackColor, - letterSpacing: -0.4, + letterSpacing: -1, decoration: isUnderLine ? TextDecoration.underline : null, ), ); @@ -132,7 +134,7 @@ extension EmailValidator on String { fontSize: 13.fSize, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, color: color ?? AppColors.blackColor, - letterSpacing: -0.4, + letterSpacing: -1, decoration: isUnderLine ? TextDecoration.underline : null), ); @@ -143,7 +145,7 @@ extension EmailValidator on String { style: TextStyle( color: color ?? AppColors.blackColor, fontSize: 14.fSize, - letterSpacing: -0.4, + letterSpacing: -1, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), decoration: isUnderLine ? TextDecoration.underline : null), ); @@ -155,7 +157,7 @@ extension EmailValidator on String { style: TextStyle( color: color ?? AppColors.blackColor, fontSize: 15.fSize, - letterSpacing: -0.4, + letterSpacing: -1, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), decoration: isUnderLine ? TextDecoration.underline : null), ); @@ -167,6 +169,8 @@ extension EmailValidator on String { bool isCenter = false, int? maxlines, TextAlign? textAlign, + FontWeight? weight, + double? letterSpacing = -0.4, }) => Text( this, @@ -175,8 +179,8 @@ extension EmailValidator on String { style: TextStyle( color: color ?? AppColors.blackColor, fontSize: 16.fSize, - letterSpacing: -0.4, - fontWeight: isBold ? FontWeight.bold : FontWeight.normal, + letterSpacing: letterSpacing, + fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal), decoration: isUnderLine ? TextDecoration.underline : null, ), ); @@ -184,7 +188,7 @@ extension EmailValidator on String { 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.fSize, letterSpacing: -0.4, fontWeight: isBold ? FontWeight.bold : FontWeight.normal), + style: TextStyle(color: color ?? AppColors.blackColor, fontSize: 17.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal), ); Widget toText18({Color? color, bool isBold = false, bool isCenter = false, int? maxlines}) => Text( @@ -207,19 +211,19 @@ extension EmailValidator on String { Widget toText21({Color? color, bool isBold = false, FontWeight? weight, int? maxlines}) => Text( this, maxLines: maxlines, - style: TextStyle(color: color ?? AppColors.blackColor, fontSize: 21.fSize, letterSpacing: -0.4, fontWeight: weight ?? (isBold ? FontWeight.bold : FontWeight.normal)), + style: TextStyle(color: color ?? AppColors.blackColor, fontSize: 21.fSize, 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.fSize, letterSpacing: -0.4, fontWeight: isBold ? FontWeight.bold : FontWeight.normal), + style: TextStyle(height: 1, color: color ?? AppColors.blackColor, fontSize: 22.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal), ); Widget toText24({Color? color, bool isBold = false, bool isCenter = false}) => Text( this, textAlign: isCenter ? TextAlign.center : null, - style: TextStyle(height: 23 / 24, color: color ?? AppColors.blackColor, fontSize: 24.fSize, letterSpacing: -0.4, fontWeight: isBold ? FontWeight.bold : FontWeight.normal), + style: TextStyle(height: 23 / 24, color: color ?? AppColors.blackColor, fontSize: 24.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal), ); Widget toText26({Color? color, bool isBold = false, double? height, bool isCenter = false}) => Text( @@ -228,24 +232,21 @@ extension EmailValidator on String { style: TextStyle(height: height ?? 23 / 26, color: color ?? AppColors.blackColor, fontSize: 26.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal), ); - Widget toText28({Color? color, bool isBold = false, double? height, bool isCenter = false}) => Text( - this, - textAlign: isCenter ? TextAlign.center : null, - style: TextStyle(height: height ?? 23 / 28, color: color ?? AppColors.blackColor, fontSize: 28.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal), - ); - - + this, + textAlign: isCenter ? TextAlign.center : null, + style: TextStyle(height: height ?? 23 / 28, color: color ?? AppColors.blackColor, fontSize: 28.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal), + ); Widget toText32({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.fSize, letterSpacing: -0.4, fontWeight: isBold ? FontWeight.bold : FontWeight.normal), + style: TextStyle(height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 32.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal), ); Widget toText44({Color? color, bool isBold = false}) => Text( this, - style: TextStyle(height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 44.fSize, letterSpacing: -0.4, fontWeight: isBold ? FontWeight.bold : FontWeight.normal), + style: TextStyle(height: 32 / 32, color: color ?? AppColors.blackColor, fontSize: 44.fSize, letterSpacing: -1, fontWeight: isBold ? FontWeight.bold : FontWeight.normal), ); Widget toSectionHeading({String upperHeading = "", String lowerHeading = ""}) { diff --git a/lib/features/authentication/authentication_repo.dart b/lib/features/authentication/authentication_repo.dart index 0be6eaf..f8ceff4 100644 --- a/lib/features/authentication/authentication_repo.dart +++ b/lib/features/authentication/authentication_repo.dart @@ -1,13 +1,10 @@ import 'dart:async'; -import 'dart:io'; import 'package:dartz/dartz.dart'; import 'package:hmg_patient_app_new/core/api/api_client.dart'; import 'package:hmg_patient_app_new/core/api_consts.dart'; import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart'; import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart'; -import 'package:hmg_patient_app_new/features/authentication/models/request_models/check_patient_authentication_request_model.dart'; -import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_activation_code_resp_model.dart'; import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart'; @@ -16,11 +13,19 @@ abstract class AuthenticationRepo { required String firebaseToken, }); - Future>> checkPatientAuthentication({ - required CheckPatientAuthenticationReq checkPatientAuthenticationReq, + Future>> checkPatientAuthentication({required dynamic checkPatientAuthenticationReq}); + + Future>> sendActivationCodeRepo({ + required dynamic sendActivationCodeReq, + String? languageID, + bool isRegister = false, }); - Future>> sendActivationCodeRegister({required CheckPatientAuthenticationReq checkPatientAuthenticationReq, String? languageID}); + Future>> checkActivationCodeRepo({ + required dynamic newRequest, // could be CheckActivationCodeReq or CheckActivationCodeRegisterReq + required String? activationCode, + required bool isRegister, + }); } class AuthenticationRepoImp implements AuthenticationRepo { @@ -41,7 +46,7 @@ class AuthenticationRepoImp implements AuthenticationRepo { onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; }, - onSuccess: (response, statusCode, {messageStatus}) { + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { try { final list = response['Patient_SELECTDeviceIMEIbyIMEIList']; if (list == null || list.isEmpty) { @@ -52,7 +57,7 @@ class AuthenticationRepoImp implements AuthenticationRepo { apiResponse = GenericApiModel( messageStatus: messageStatus, statusCode: statusCode, - errorMessage: null, + errorMessage: errorMessage, data: model, ); } catch (e) { @@ -70,33 +75,26 @@ class AuthenticationRepoImp implements AuthenticationRepo { @override Future>> checkPatientAuthentication({ - required CheckPatientAuthenticationReq checkPatientAuthenticationReq, + required dynamic checkPatientAuthenticationReq, String? languageID, }) async { int isOutKsa = (checkPatientAuthenticationReq.zipCode == '966' || checkPatientAuthenticationReq.zipCode == '+966') ? 0 : 1; - //TODO : We will use all these from AppState directly in the ApiClient - - checkPatientAuthenticationReq.versionID = VERSION_ID; - checkPatientAuthenticationReq.channel = CHANNEL; - checkPatientAuthenticationReq.iPAdress = IP_ADDRESS; - checkPatientAuthenticationReq.generalid = GENERAL_ID; - checkPatientAuthenticationReq.languageID = (languageID == 'ar' ? 1 : 2); checkPatientAuthenticationReq.patientOutSA = isOutKsa; try { GenericApiModel? apiResponse; Failure? failure; await apiClient.post( - ApiConsts.selectDeviceImei, + ApiConsts.checkPatientAuth, body: checkPatientAuthenticationReq.toJson(), onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; }, - onSuccess: (response, statusCode, {messageStatus}) { + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { try { apiResponse = GenericApiModel( messageStatus: messageStatus, statusCode: statusCode, - errorMessage: null, + errorMessage: errorMessage, data: response, ); } catch (e) { @@ -113,41 +111,86 @@ class AuthenticationRepoImp implements AuthenticationRepo { } @override - Future>> sendActivationCodeRegister({required CheckPatientAuthenticationReq checkPatientAuthenticationReq, String? languageID}) async { - int isOutKsa = (checkPatientAuthenticationReq.zipCode == '966' || checkPatientAuthenticationReq.zipCode == '+966') ? 0 : 1; - //TODO : We will use all these from AppState directly in the ApiClient - - checkPatientAuthenticationReq.versionID = VERSION_ID; - checkPatientAuthenticationReq.channel = CHANNEL; - checkPatientAuthenticationReq.iPAdress = IP_ADDRESS; - checkPatientAuthenticationReq.generalid = GENERAL_ID; - checkPatientAuthenticationReq.languageID = (languageID == 'ar' ? 1 : 2); - checkPatientAuthenticationReq.deviceTypeID = Platform.isIOS ? 1 : 2; - checkPatientAuthenticationReq.patientOutSA = isOutKsa; - checkPatientAuthenticationReq.isDentalAllowedBackend = false; + Future>> sendActivationCodeRepo({ + required dynamic sendActivationCodeReq, + String? languageID, + bool isRegister = false, + }) async { + int isOutKsa = (sendActivationCodeReq.zipCode == '966' || sendActivationCodeReq.zipCode == '+966') ? 0 : 1; + sendActivationCodeReq.patientOutSA = isOutKsa; + sendActivationCodeReq.isDentalAllowedBackend = false; try { GenericApiModel? apiResponse; Failure? failure; + await apiClient.post( - SEND_ACTIVATION_CODE_REGISTER, - body: checkPatientAuthenticationReq.toJson(), + isRegister ? ApiConsts.sendActivationCodeRegister : ApiConsts.sendActivationCode, + body: sendActivationCodeReq.toJson(), + onFailure: (error, statusCode, {messageStatus, failureType}) { + failure = failureType; + }, + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { + try { + apiResponse = GenericApiModel( + messageStatus: messageStatus, + statusCode: statusCode, + errorMessage: errorMessage, + 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>> checkActivationCodeRepo({ + required dynamic newRequest, // could be CheckActivationCodeReq or CheckActivationCodeRegisterReq + required String? activationCode, + required bool isRegister, + }) async { + newRequest.activationCode = activationCode ?? "0000"; + newRequest.isSilentLogin = activationCode != null ? false : true; + newRequest.projectOutSA = newRequest.zipCode == '966' ? false : true; + newRequest.isDentalAllowedBackend = false; + newRequest.forRegisteration = newRequest.isRegister ?? false; + newRequest.isRegister = false; + + final endpoint = isRegister ? ApiConsts.checkActivationCodeRegister : ApiConsts.checkActivationCode; + + try { + GenericApiModel? apiResponse; + Failure? failure; + + await apiClient.post( + endpoint, + body: newRequest.toJson(), onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; }, - onSuccess: (response, statusCode, {messageStatus}) { + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { try { apiResponse = GenericApiModel( messageStatus: messageStatus, statusCode: statusCode, - errorMessage: null, - data: CheckActivationCode.fromJson(response), + errorMessage: errorMessage, + 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!); diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart index c34c339..e856d3e 100644 --- a/lib/features/authentication/authentication_view_model.dart +++ b/lib/features/authentication/authentication_view_model.dart @@ -1,29 +1,43 @@ import 'dart:convert'; +import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/common_models/nationality_country_model.dart'; import 'package:hmg_patient_app_new/core/enums.dart'; +import 'package:hmg_patient_app_new/core/utils/loading_utils.dart'; import 'package:hmg_patient_app_new/core/utils/request_utils.dart'; -import 'package:hmg_patient_app_new/core/utils/utils.dart'; +import 'package:hmg_patient_app_new/core/utils/validation_utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_repo.dart'; -import 'package:hmg_patient_app_new/features/authentication/models/request_models/check_patient_authentication_request_model.dart'; +import 'package:hmg_patient_app_new/features/authentication/models/resp_models/check_activation_code_resp_model.dart'; +import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart'; +import 'package:hmg_patient_app_new/presentation/authentication/login.dart'; +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'; import 'package:hmg_patient_app_new/services/error_handler_service.dart'; +import 'package:hmg_patient_app_new/services/navigation_service.dart'; class AuthenticationViewModel extends ChangeNotifier { - AuthenticationRepo authenticationRepo; - AppState appState; - ErrorHandlerService errorHandlerService; - DialogService dialogService; + final AuthenticationRepo _authenticationRepo; + final AppState _appState; + final ErrorHandlerService _errorHandlerService; + final DialogService _dialogService; + final NavigationService _navigationService; AuthenticationViewModel({ - required this.appState, - required this.authenticationRepo, - required this.errorHandlerService, - required this.dialogService, - }); + required AppState appState, + required AuthenticationRepo authenticationRepo, + required ErrorHandlerService errorHandlerService, + required DialogService dialogService, + required NavigationService navigationService, + required CacheService cacheService, + }) : _navigationService = navigationService, + _dialogService = dialogService, + _errorHandlerService = errorHandlerService, + _appState = appState, + _authenticationRepo = authenticationRepo; final TextEditingController nationalIdController = TextEditingController(), phoneNumberController = TextEditingController(), dobController = TextEditingController(); CountryEnum selectedCountrySignup = CountryEnum.saudiArabia; @@ -31,11 +45,46 @@ class AuthenticationViewModel extends ChangeNotifier { GenderTypeEnum? genderType; bool isTermsAccepted = false; List? countriesList; + NationalityCountries? pickedCountryByUAEUser; - void login() { - if (ValidationUtils.isValidatePhoneAndId(nationalId: nationalIdController.text, phoneNumber: phoneNumberController.text)) { - } else {} + bool isDubai = false; + bool authenticated = false; + late int mobileNumber; + String errorMsg = ''; + var registerd_data; + bool isMoreOption = false; + var zipCode; + var patientOutSA; + var loginTokenID; + var loginType; + var deviceToken; + var lastLogin; + final FocusNode myFocusNode = FocusNode(); + late int selectedOption = 1; + bool onlySMSBox = false; + int fingrePrintBefore = 0; + var dob; + late int isHijri; + var healthId; + + Future onLoginPressed() async { + try { + LoadingUtils.showFullScreenLoader(); + //TODO: We will remove this delay + await Future.delayed(Duration(seconds: 3)); + var data = _appState.getSelectDeviceByImeiRespModelElement; + log("Cached IMEI data: ${data?.toJson()}"); + if (data != null) { + await _handleExistingImeiData(data); + } else { + await _handleNewImeiRegistration(); + } + } catch (e) { + log("Error in onLoginPressed: $e"); + LoadingUtils.hideFullScreenLoader(); + _dialogService.showErrorBottomSheet(message: "An unexpected error occurred. Please try again.", onOkPressed: () {}); + } } void clearDefaults() { @@ -84,112 +133,285 @@ class AuthenticationViewModel extends ChangeNotifier { notifyListeners(); } - Future selectDeviceImei({Function(dynamic)? onSuccess, Function(String)? onError}) async { - String firebaseToken = "dOGRRszQQMGe_9wA5Hx3kO:APA91bFV5IcIJXvcCXXk0tc2ddtZgWwCPq7sGSuPr-YW7iiJpQZKgFGN9GAzCVOWL8MfheaP1slE8MdxB7lczdPBGdONQ7WbMmhgHcsUCUktq-hsapGXXqc"; - final result = await authenticationRepo.selectDeviceByImei(firebaseToken: firebaseToken); + Future selectDeviceImei({required Function(dynamic data) onSuccess, Function(String)? onError}) async { + // LoadingUtils.showFullScreenLoading(); + String firebaseToken = _appState.deviceToken == "" + ? "dOGRRszQQMGe_9wA5Hx3kO:APA91bFV5IcIJXvcCXXk0tc2ddtZgWwCPq7sGSuPr-YW7iiJpQZKgFGN9GAzCVOWL8MfheaP1slE8MdxB7lczdPBGdONQ7WbMmhgHcsUCUktq-hsapGXXqc" + : _appState.deviceToken; + final result = await _authenticationRepo.selectDeviceByImei(firebaseToken: firebaseToken); result.fold( - (failure) async => await errorHandlerService.handleError(failure: failure), + (failure) async { + // LoadingUtils.hideFullScreenLoader(); + await _errorHandlerService.handleError(failure: failure); + }, (apiResponse) { + // LoadingUtils.hideFullScreenLoader(); + log("apiResponse: ${apiResponse.data.toString()}"); + log("messageStatus: ${apiResponse.messageStatus.toString()}"); + if (apiResponse.messageStatus == 1) { + onSuccess(apiResponse.data); + } else if (apiResponse.messageStatus == 2) { + _dialogService.showErrorBottomSheet(message: "Message Status = 2", onOkPressed: () {}); + } + }, + ); + } + + Future _handleExistingImeiData(dynamic data) async { + try { + SelectDeviceByImeiRespModelElement? savedData = _appState.getSelectDeviceByImeiRespModelElement; + LoadingUtils.hideFullScreenLoader(); + + if (savedData != null) { + // TODO: Navigate to SavedLogin when available + _navigationService.pushPage(page: LoginScreen()); + // navigationService.pushPage(page: SavedLogin(savedData)); + } + } catch (e) { + log("Error handling existing IMEI data: $e"); + LoadingUtils.hideFullScreenLoader(); + _navigationService.pushPage(page: LoginScreen()); + } + } + + Future _handleNewImeiRegistration() async { + await selectDeviceImei(onSuccess: (dynamic respData) async { + try { + if (respData != null) { + dynamic data = SelectDeviceByImeiRespModelElement.fromJson(respData.toJson()); + _appState.setSelectDeviceByImeiRespModelElement(data); + LoadingUtils.hideFullScreenLoader(); + + // TODO: Navigate to SavedLogin when available + // SelectDeviceByImeiRespModelElement savedData = + // SelectDeviceByImeiRespModelElement.fromJson(respData); + // navigationService.pushPage(page: SavedLogin(savedData)); + _navigationService.pushPage(page: LoginScreen()); + } else { + LoadingUtils.hideFullScreenLoader(); + _navigationService.pushPage(page: LoginScreen()); + } + } catch (e) { + log("Error processing IMEI registration response: $e"); + LoadingUtils.hideFullScreenLoader(); + _navigationService.pushPage(page: LoginScreen()); + } + }, onError: (String error) { + LoadingUtils.hideFullScreenLoader(); + _dialogService.showErrorBottomSheet(message: error, onOkPressed: () {}); + }); + } + + Future checkUserAuthentication({required OTPTypeEnum otpTypeEnum, Function(dynamic)? onSuccess, Function(String)? onError}) async { + // TODO: THIS SHOULD BE REMOVED LATER ON AND PASSED FROM APP STATE DIRECTLY INTO API CLIENT. BECAUSE THIS API ONLY NEEDS FEW PARAMS FROM USER + + if (phoneNumberController.text.isEmpty) { + phoneNumberController.text = "504278212"; + } + bool isValidated = ValidationUtils.isValidatePhoneAndId( + phoneNumber: phoneNumberController.text, + nationalId: nationalIdController.text, + ); + + if (!isValidated) { + return; + } + + LoadingUtils.showFullScreenLoader(); + + dynamic checkPatientAuthenticationReq = RequestUtils.getPatientAuthenticationRequest( + phoneNumber: phoneNumberController.text, + nationId: nationalIdController.text, + isForRegister: false, + patientOutSA: false, + otpTypeEnum: otpTypeEnum, + patientId: 0, + zipCode: '966', + ); + + final result = await _authenticationRepo.checkPatientAuthentication(checkPatientAuthenticationReq: checkPatientAuthenticationReq); + LoadingUtils.hideFullScreenLoader(); + result.fold( + (failure) async => await _errorHandlerService.handleError(failure: failure), + (apiResponse) async { if (apiResponse.messageStatus == 2) { - dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {}); + await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty", onOkPressed: () {}); } else if (apiResponse.messageStatus == 1) { - //todo: move to next api call + if (apiResponse.data['isSMSSent']) { + _appState.setAppLoginTokenID = apiResponse.data['LogInTokenID']; + sendActivationCode( + otpTypeEnum: otpTypeEnum, + phoneNumber: phoneNumberController.text, + nationalIdOrFileNumber: nationalIdController.text, + ); + } else { + if (apiResponse.data['IsAuthenticated']) { + await checkActivationCode( + onWrongActivationCode: (String? message) {}, + activationCode: 0000, + ); + } + } + } + }, + ); + } + + Future sendActivationCode({ + required OTPTypeEnum otpTypeEnum, + required String nationalIdOrFileNumber, + required String phoneNumber, + }) async { + var request = RequestUtils.getCommonRequestSendActivationCode( + otpTypeEnum: otpTypeEnum, + mobileNumber: phoneNumber, + selectedLoginType: otpTypeEnum.toInt(), + zipCode: "966", + nationalId: nationalIdOrFileNumber, + isFileNo: false, + patientId: 0, + isForRegister: false, + patientOutSA: false, + ); + + // TODO: GET APP SMS SIGNATURE HERE + request.sMSSignature = "enKTDcqbOVd"; + // GifLoaderDialogUtils.showMyDialog(context); + + bool isForRegister = healthId != null || isDubai; + if (isForRegister) { + if (!isDubai) { + request.dob = dob; //isHijri == 1 ? dob : dateFormat2.format(dateFormat.parse(dob)); + } + request.healthId = healthId; + request.isHijri = isHijri; + } else { + // request.dob = ""; + // request.healthId = ""; + // request.isHijri = 0; + } + + final resultEither = await _authenticationRepo.sendActivationCodeRepo( + sendActivationCodeReq: request, + isRegister: isForRegister, + languageID: 'er', + ); + + resultEither.fold( + (failure) async => await _errorHandlerService.handleError(failure: failure), + (apiResponse) async { + if (apiResponse.messageStatus == 2) { + await _dialogService.showErrorBottomSheet(message: apiResponse.errorMessage ?? "ErrorEmpty"); + } else { + if (apiResponse.data != null && apiResponse.data['isSMSSent'] == true) { + navigateToOTPScreen(otpTypeEnum: otpTypeEnum, phoneNumber: phoneNumber); + } else { + // TODO: Handle isSMSSent false + // navigateToOTPScreen(otpTypeEnum: otpTypeEnum, phoneNumber: phoneNumber); + } } }, ); } -// Future checkUserAuthentication({Function(dynamic)? onSuccess, Function(String)? onError}) async { -// CheckPatientAuthenticationReq checkPatientAuthenticationReq = RequestUtils.getCommonRequestWelcome( -// phoneNumber: '0567184134', -// otpTypeEnum: OTPTypeEnum.sms, -// deviceToken: 'dummyDeviceToken123', -// patientOutSA: true, -// loginTokenID: 'dummyLoginToken456', -// registeredData: null, -// patientId: 12345, -// nationIdText: '1234567890', -// countryCode: 'SA', -// ); -// -// final result = await authenticationRepo.checkPatientAuthentication(checkPatientAuthenticationReq: checkPatientAuthenticationReq); -// result.fold( -// (failure) async => await errorHandlerService.handleError(failure: failure), -// (apiResponse) { -// if (apiResponse.data['isSMSSent']) { -// // TODO: set this in AppState -// // sharedPref.setString(LOGIN_TOKEN_ID, value['LogInTokenID']); -// // loginTokenID = value['LogInTokenID'], -// // sharedPref.setObject(REGISTER_DATA_FOR_LOGIIN, request), -// sendActivationCode(type); -// } else { -// if (apiResponse.data['IsAuthenticated']) { -// checkActivationCode(onWrongActivationCode: (String? message) {}); -// } -// } -// }, -// ); -// } - -// Future sendActivationCode({required OTPTypeEnum otpTypeEnum}) async { -// var request = RequestUtils.getCommonRequestAuthProvider( -// otpTypeEnum: otpTypeEnum, -// registeredData: null, -// deviceToken: "dummyLoginToken456", -// mobileNumber: "0567184134", -// zipCode: "SA", -// patientOutSA: true, -// loginTokenID: "dummyLoginToken456", -// selectedOption: selectedOption, -// patientId: 12345, -// ); -// -// request.sMSSignature = await SMSOTP.getSignature(); -// selectedOption = type; -// // GifLoaderDialogUtils.showMyDialog(context); -// if (healthId != null || isDubai) { -// if (!isDubai) { -// request.dob = dob; //isHijri == 1 ? dob : dateFormat2.format(dateFormat.parse(dob)); -// } -// request.healthId = healthId; -// request.isHijri = isHijri; -// await this.apiClient.sendActivationCodeRegister(request).then((result) { -// // GifLoaderDialogUtils.hideDialog(context); -// if (result != null && result['isSMSSent'] == true) { -// this.startSMSService(type); -// } -// }).catchError((r) { -// GifLoaderDialogUtils.hideDialog(context); -// context.showBottomSheet( -// child: ExceptionBottomSheet( -// message: r.toString(), -// onOkPressed: () { -// Navigator.of(context).pop(); -// }, -// )); -// // AppToast.showErrorToast(message: r); -// }); -// } else { -// request.dob = ""; -// request.healthId = ""; -// request.isHijri = 0; -// await this.authService.sendActivationCode(request).then((result) { -// GifLoaderDialogUtils.hideDialog(context); -// if (result != null && result['isSMSSent'] == true) { -// this.startSMSService(type); -// } -// }).catchError((r) { -// GifLoaderDialogUtils.hideDialog(context); -// context.showBottomSheet( -// child: ExceptionBottomSheet( -// message: r.toString(), -// onOkPressed: () { -// Navigator.of(context).pop(); -// }, -// )); -// // AppToast.showErrorToast(message: r.toString()); -// }); -// } -// } + Future checkActivationCode({ + required int activationCode, + required Function(String? message) onWrongActivationCode, + }) async { + final request = RequestUtils.getCommonRequestWelcome( + phoneNumber: '0567184134', + otpTypeEnum: OTPTypeEnum.sms, + deviceToken: 'dummyDeviceToken123', + patientOutSA: true, + loginTokenID: 'dummyLoginToken456', + registeredData: null, + patientId: 12345, + nationIdText: '1234567890', + countryCode: 'SA', + ).toJson(); + + bool isForRegister = healthId != null || isDubai; + if (isForRegister) { + if (isDubai) request['DOB'] = dob; + request['HealthId'] = healthId; + request['IsHijri'] = isHijri; + + final resultEither = await _authenticationRepo.checkActivationCodeRepo( + newRequest: request, + activationCode: activationCode.toString(), + isRegister: true, + ); + + resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) { + final activation = CheckActivationCode.fromJson(apiResponse.data as Map); + if (registerd_data?.isRegister == true) { + _navigationService.popUntilNamed(AppRoutes.registerNewScreen); + // Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew)); + return; + } + }); + } else { + final resultEither = await _authenticationRepo.checkActivationCodeRepo( + newRequest: request, + activationCode: activationCode.toString(), + isRegister: false, + ); + + resultEither.fold((failure) async => await _errorHandlerService.handleError(failure: failure), (apiResponse) { + final activation = CheckActivationCode.fromJson(resultEither as Map); + if (activation.errorCode == '699') { + // Todo: Hide Loader + // GifLoaderDialogUtils.hideDialog(context); + onWrongActivationCode(activation.errorEndUserMessage); + return; + } else if (registerd_data?.isRegister == true) { + _navigationService.popUntilNamed(AppRoutes.registerNewScreen); + // Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew)); + return; + } else { + // TODO: setPreferences and stuff + // sharedPref.remove(FAMILY_FILE); + // activation.list!.isFamily = false; + // userData = activation.list; + // sharedPref.setString(BLOOD_TYPE, activation.patientBloodType ?? ""); + // authenticatedUserObject.user = activation.list!; + // projectViewModel.setPrivilege(privilegeList: res); + // await sharedPref.setObject(MAIN_USER, activation.list); + // await sharedPref.setObject(USER_PROFILE, activation.list); + // loginTokenID = activation.logInTokenID; + // await sharedPref.setObject(LOGIN_TOKEN_ID, activation.logInTokenID); + // await sharedPref.setString(TOKEN, activation.authenticationTokenID!); + // checkIfUserAgreedBefore(activation); + // projectViewModel.analytics.loginRegistration.login_successful(); + } + }); + } + } + + Future navigateToOTPScreen({required OTPTypeEnum otpTypeEnum, required String phoneNumber}) async { + _navigationService.pushToOtpScreen( + phoneNumber: phoneNumber, + checkActivationCode: (int activationCode) async { + await checkActivationCode( + activationCode: activationCode, + onWrongActivationCode: (String? value) { + onWrongActivationCode(message: value); + }); + }, + onResendOTPPressed: (String phoneNumber) {}, + ); + } + + Future onWrongActivationCode({String? message}) async { + // TODO: HANDLE THIS VIA BOTTOM SHEET + } + + @override + void dispose() { + nationalIdController.dispose(); + phoneNumberController.dispose(); + myFocusNode.dispose(); + super.dispose(); + } } diff --git a/lib/features/authentication/models/request_models/check_activation_code_register_request_model.dart b/lib/features/authentication/models/request_models/check_activation_code_register_request_model.dart new file mode 100644 index 0000000..d752a13 --- /dev/null +++ b/lib/features/authentication/models/request_models/check_activation_code_register_request_model.dart @@ -0,0 +1,121 @@ +class CheckActivationCodeRegisterReq { + int? patientMobileNumber; + String? mobileNo; + String? deviceToken; + bool? projectOutSA; + int? loginType; + String? zipCode; + bool? isRegister; + String? logInTokenID; + int? searchType; + int? patientID; + String? nationalID; + String? patientIdentificationID; + String? activationCode; + bool? isSilentLogin; + double? versionID; + int? channel; + int? languageID; + String? iPAdress; + String? generalid; + int? patientOutSA; + dynamic sessionID; + bool? isDentalAllowedBackend; + int? deviceTypeID; + bool? forRegisteration; + String? dob; + int? isHijri; + String? healthId; + + CheckActivationCodeRegisterReq({ + this.patientMobileNumber, + this.mobileNo, + this.deviceToken, + this.projectOutSA, + this.loginType, + this.zipCode, + this.isRegister, + this.logInTokenID, + this.searchType, + this.patientID, + this.nationalID, + this.patientIdentificationID, + this.activationCode, + this.isSilentLogin, + this.versionID, + this.channel, + this.languageID, + this.iPAdress, + this.generalid, + this.patientOutSA, + this.sessionID, + this.isDentalAllowedBackend, + this.deviceTypeID, + this.forRegisteration, + this.dob, + this.isHijri, + this.healthId, + }); + + CheckActivationCodeRegisterReq.fromJson(Map json) { + patientMobileNumber = json['PatientMobileNumber']; + mobileNo = json['MobileNo']; + deviceToken = json['DeviceToken']; + projectOutSA = json['ProjectOutSA']; + loginType = json['LoginType']; + zipCode = json['ZipCode']; + isRegister = json['isRegister']; + logInTokenID = json['LogInTokenID']; + searchType = json['SearchType']; + patientID = json['PatientID']; + nationalID = json['NationalID']; + patientIdentificationID = json['PatientIdentificationID']; + activationCode = json['activationCode']; + isSilentLogin = json['IsSilentLogin']; + versionID = json['VersionID']; + channel = json['Channel']; + languageID = json['LanguageID']; + iPAdress = json['IPAdress']; + generalid = json['generalid']; + patientOutSA = json['PatientOutSA']; + sessionID = json['SessionID']; + isDentalAllowedBackend = json['isDentalAllowedBackend']; + deviceTypeID = json['DeviceTypeID']; + forRegisteration = json['ForRegisteration']; + dob = json['DOB']; + isHijri = json['IsHijri']; + healthId = json['HealthId']; + } + + Map toJson() { + final Map data = {}; + data['PatientMobileNumber'] = patientMobileNumber; + data['MobileNo'] = mobileNo; + data['DeviceToken'] = deviceToken; + data['ProjectOutSA'] = projectOutSA; + data['LoginType'] = loginType; + data['ZipCode'] = zipCode; + data['isRegister'] = isRegister; + data['LogInTokenID'] = logInTokenID; + data['SearchType'] = searchType; + data['PatientID'] = patientID; + data['NationalID'] = nationalID; + data['PatientIdentificationID'] = patientIdentificationID; + data['activationCode'] = activationCode; + data['IsSilentLogin'] = isSilentLogin; + data['VersionID'] = versionID; + data['Channel'] = channel; + data['LanguageID'] = languageID; + data['IPAdress'] = iPAdress; + data['generalid'] = generalid; + data['PatientOutSA'] = patientOutSA; + data['SessionID'] = sessionID; + data['isDentalAllowedBackend'] = isDentalAllowedBackend; + data['DeviceTypeID'] = deviceTypeID; + data['ForRegisteration'] = forRegisteration; + data['DOB'] = dob; + data['IsHijri'] = isHijri; + data['HealthId'] = healthId; + return data; + } +} diff --git a/lib/features/authentication/models/request_models/send_activation_request_model.dart b/lib/features/authentication/models/request_models/send_activation_request_model.dart index dc3d55d..360efd4 100644 --- a/lib/features/authentication/models/request_models/send_activation_request_model.dart +++ b/lib/features/authentication/models/request_models/send_activation_request_model.dart @@ -29,38 +29,38 @@ class SendActivationRequest { int? status; int? familyRegionID; bool? isPatientExcluded; + SendActivationRequest( {this.patientMobileNumber, - this.mobileNo, - this.deviceToken, - this.projectOutSA, - this.loginType, - this.zipCode, - this.isRegister, - this.logInTokenID, - this.searchType, - this.patientID, - this.nationalID, - this.patientIdentificationID, - this.oTPSendType, - this.languageID, - this.versionID, - this.channel, - this.iPAdress, - this.generalid, - this.patientOutSA, - this.sessionID, - this.isDentalAllowedBackend, - this.deviceTypeID, - this.sMSSignature, - this.dob, - this.isHijri, - this.healthId, - this.responseID, - this.status, - this.familyRegionID, - this.isPatientExcluded - }); + this.mobileNo, + this.deviceToken, + this.projectOutSA, + this.loginType, + this.zipCode, + this.isRegister, + this.logInTokenID, + this.searchType, + this.patientID, + this.nationalID, + this.patientIdentificationID, + this.oTPSendType, + this.languageID, + this.versionID, + this.channel, + this.iPAdress, + this.generalid, + this.patientOutSA, + this.sessionID, + this.isDentalAllowedBackend, + this.deviceTypeID, + this.sMSSignature, + this.dob, + this.isHijri, + this.healthId, + this.responseID, + this.status, + this.familyRegionID, + this.isPatientExcluded}); SendActivationRequest.fromJson(Map json) { patientMobileNumber = json['PatientMobileNumber']; diff --git a/lib/features/authentication/models/resp_models/check_activation_code_resp_model.dart b/lib/features/authentication/models/resp_models/check_activation_code_resp_model.dart index 8610e08..89a101b 100644 --- a/lib/features/authentication/models/resp_models/check_activation_code_resp_model.dart +++ b/lib/features/authentication/models/resp_models/check_activation_code_resp_model.dart @@ -269,257 +269,6 @@ class CheckActivationCode { } } -class List { - String? setupID; - int? patientType; - int? patientID; - String? firstName; - String? middleName; - String? lastName; - String? firstNameN; - String? middleNameN; - String? lastNameN; - int? relationshipID; - int? gender; - String? dateofBirth; - dynamic dateofBirthN; - String? nationalityID; - dynamic phoneResi; - dynamic phoneOffice; - String? mobileNumber; - dynamic faxNumber; - String? emailAddress; - dynamic bloodGroup; - dynamic rHFactor; - bool? isEmailAlertRequired; - bool? isSMSAlertRequired; - String? preferredLanguage; - bool? isPrivilegedMember; - dynamic memberID; - dynamic expiryDate; - dynamic isHmgEmployee; - dynamic employeeID; - dynamic emergencyContactName; - dynamic emergencyContactNo; - int? patientPayType; - dynamic dHCCPatientRefID; - bool? isPatientDummy; - int? status; - dynamic isStatusCleared; - int? patientIdentificationType; - String? patientIdentificationNo; - int? projectID; - int? infoSourceID; - dynamic address; - int? age; - String? ageDesc; - int? areaID; - int? createdBy; - String? genderDescription; - dynamic iR; - dynamic iSOCityID; - dynamic iSOCountryID; - ListPrivilege? listPrivilege; - dynamic marital; - int? outSA; - dynamic pOBox; - bool? receiveHealthSummaryReport; - int? sourceType; - dynamic strDateofBirth; - dynamic tempAddress; - dynamic zipCode; - - List({ - this.setupID, - this.patientType, - this.patientID, - this.firstName, - this.middleName, - this.lastName, - this.firstNameN, - this.middleNameN, - this.lastNameN, - this.relationshipID, - this.gender, - this.dateofBirth, - this.dateofBirthN, - this.nationalityID, - this.phoneResi, - this.phoneOffice, - this.mobileNumber, - this.faxNumber, - this.emailAddress, - this.bloodGroup, - this.rHFactor, - this.isEmailAlertRequired, - this.isSMSAlertRequired, - this.preferredLanguage, - this.isPrivilegedMember, - this.memberID, - this.expiryDate, - this.isHmgEmployee, - this.employeeID, - this.emergencyContactName, - this.emergencyContactNo, - this.patientPayType, - this.dHCCPatientRefID, - this.isPatientDummy, - this.status, - this.isStatusCleared, - this.patientIdentificationType, - this.patientIdentificationNo, - this.projectID, - this.infoSourceID, - this.address, - this.age, - this.ageDesc, - this.areaID, - this.createdBy, - this.genderDescription, - this.iR, - this.iSOCityID, - this.iSOCountryID, - this.listPrivilege, - this.marital, - this.outSA, - this.pOBox, - this.receiveHealthSummaryReport, - this.sourceType, - this.strDateofBirth, - this.tempAddress, - this.zipCode, - }); - - List.fromJson(Map json) { - setupID = json['SetupID']; - patientType = json['PatientType']; - patientID = json['PatientID']; - firstName = json['FirstName']; - middleName = json['MiddleName']; - lastName = json['LastName']; - firstNameN = json['FirstNameN']; - middleNameN = json['MiddleNameN']; - lastNameN = json['LastNameN']; - relationshipID = json['RelationshipID']; - gender = json['Gender']; - dateofBirth = json['DateofBirth']; - dateofBirthN = json['DateofBirthN']; - nationalityID = json['NationalityID']; - phoneResi = json['PhoneResi']; - phoneOffice = json['PhoneOffice']; - mobileNumber = json['MobileNumber']; - faxNumber = json['FaxNumber']; - emailAddress = json['EmailAddress']; - bloodGroup = json['BloodGroup']; - rHFactor = json['RHFactor']; - isEmailAlertRequired = json['IsEmailAlertRequired']; - isSMSAlertRequired = json['IsSMSAlertRequired']; - preferredLanguage = json['PreferredLanguage']; - isPrivilegedMember = json['IsPrivilegedMember']; - memberID = json['MemberID']; - expiryDate = json['ExpiryDate']; - isHmgEmployee = json['IsHmgEmployee']; - employeeID = json['EmployeeID']; - emergencyContactName = json['EmergencyContactName']; - emergencyContactNo = json['EmergencyContactNo']; - patientPayType = json['PatientPayType']; - dHCCPatientRefID = json['DHCCPatientRefID']; - isPatientDummy = json['IsPatientDummy']; - status = json['Status']; - isStatusCleared = json['IsStatusCleared']; - patientIdentificationType = json['PatientIdentificationType']; - patientIdentificationNo = json['PatientIdentificationNo']; - projectID = json['ProjectID']; - infoSourceID = json['InfoSourceID']; - address = json['Address']; - age = json['Age']; - ageDesc = json['AgeDesc']; - areaID = json['AreaID']; - createdBy = json['CreatedBy']; - genderDescription = json['GenderDescription']; - iR = json['IR']; - iSOCityID = json['ISOCityID']; - iSOCountryID = json['ISOCountryID']; - if (json['ListPrivilege'] != null) { - listPrivilege = ListPrivilege.fromJson(json['ListPrivilege']); - } - marital = json['Marital']; - outSA = json['OutSA']; - pOBox = json['POBox']; - receiveHealthSummaryReport = json['ReceiveHealthSummaryReport']; - sourceType = json['SourceType']; - strDateofBirth = json['StrDateofBirth']; - tempAddress = json['TempAddress']; - zipCode = json['ZipCode']; - } - - Map toJson() { - final Map data = {}; - data['SetupID'] = setupID; - data['PatientType'] = patientType; - data['PatientID'] = patientID; - data['FirstName'] = firstName; - data['MiddleName'] = middleName; - data['LastName'] = lastName; - data['FirstNameN'] = firstNameN; - data['MiddleNameN'] = middleNameN; - data['LastNameN'] = lastNameN; - data['RelationshipID'] = relationshipID; - data['Gender'] = gender; - data['DateofBirth'] = dateofBirth; - data['DateofBirthN'] = dateofBirthN; - data['NationalityID'] = nationalityID; - data['PhoneResi'] = phoneResi; - data['PhoneOffice'] = phoneOffice; - data['MobileNumber'] = mobileNumber; - data['FaxNumber'] = faxNumber; - data['EmailAddress'] = emailAddress; - data['BloodGroup'] = bloodGroup; - data['RHFactor'] = rHFactor; - data['IsEmailAlertRequired'] = isEmailAlertRequired; - data['IsSMSAlertRequired'] = isSMSAlertRequired; - data['PreferredLanguage'] = preferredLanguage; - data['IsPrivilegedMember'] = isPrivilegedMember; - data['MemberID'] = memberID; - data['ExpiryDate'] = expiryDate; - data['IsHmgEmployee'] = isHmgEmployee; - data['EmployeeID'] = employeeID; - data['EmergencyContactName'] = emergencyContactName; - data['EmergencyContactNo'] = emergencyContactNo; - data['PatientPayType'] = patientPayType; - data['DHCCPatientRefID'] = dHCCPatientRefID; - data['IsPatientDummy'] = isPatientDummy; - data['Status'] = status; - data['IsStatusCleared'] = isStatusCleared; - data['PatientIdentificationType'] = patientIdentificationType; - data['PatientIdentificationNo'] = patientIdentificationNo; - data['ProjectID'] = projectID; - data['InfoSourceID'] = infoSourceID; - data['Address'] = address; - data['Age'] = age; - data['AgeDesc'] = ageDesc; - data['AreaID'] = areaID; - data['CreatedBy'] = createdBy; - data['GenderDescription'] = genderDescription; - data['IR'] = iR; - data['ISOCityID'] = iSOCityID; - data['ISOCountryID'] = iSOCountryID; - if (listPrivilege != null) { - data['ListPrivilege'] = listPrivilege; - } - data['Marital'] = marital; - data['OutSA'] = outSA; - data['POBox'] = pOBox; - data['ReceiveHealthSummaryReport'] = receiveHealthSummaryReport; - data['SourceType'] = sourceType; - data['StrDateofBirth'] = strDateofBirth; - data['TempAddress'] = tempAddress; - data['ZipCode'] = zipCode; - - return data; - } -} - class ListPrivilege { int? iD; String? serviceName; diff --git a/lib/widgets/otp/otp.dart b/lib/features/authentication/widgets/otp_verification_screen.dart similarity index 92% rename from lib/widgets/otp/otp.dart rename to lib/features/authentication/widgets/otp_verification_screen.dart index 81c375b..9ea1b9e 100644 --- a/lib/widgets/otp/otp.dart +++ b/lib/features/authentication/widgets/otp_verification_screen.dart @@ -1,4 +1,5 @@ import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; @@ -6,16 +7,23 @@ import 'package:hmg_patient_app_new/presentation/authentication/register_step2.d import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/appbar/app_bar_widget.dart'; -class OTPVerificationPage extends StatefulWidget { +class OTPVerificationScreen extends StatefulWidget { final String phoneNumber; + final Function(int code) checkActivationCode; + final Function(String phoneNumber) onResendOTPPressed; - const OTPVerificationPage({Key? key, required this.phoneNumber}) : super(key: key); + const OTPVerificationScreen({ + super.key, + required this.phoneNumber, + required this.checkActivationCode, + required this.onResendOTPPressed, + }); @override - State createState() => _OTPVerificationPageState(); + State createState() => _OTPVerificationScreenState(); } -class _OTPVerificationPageState extends State { +class _OTPVerificationScreenState extends State { final int _otpLength = 4; late final List _controllers; late final List _focusNodes; @@ -41,8 +49,12 @@ class _OTPVerificationPageState extends State { @override void dispose() { - for (final c in _controllers) c.dispose(); - for (final f in _focusNodes) f.dispose(); + for (final c in _controllers) { + c.dispose(); + } + for (final f in _focusNodes) { + f.dispose(); + } _resendTimer?.cancel(); super.dispose(); } diff --git a/lib/features/insurance/insurance_repo.dart b/lib/features/insurance/insurance_repo.dart index a5c624f..536556f 100644 --- a/lib/features/insurance/insurance_repo.dart +++ b/lib/features/insurance/insurance_repo.dart @@ -3,11 +3,17 @@ 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/insurance/models/resp_models/patient_insurance_card_history.dart'; import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_details_response_model.dart'; +import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_update_response_model.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart'; abstract class InsuranceRepo { Future>>> getPatientInsuranceDetails({required String patientId}); + + Future>>> getPatientInsuranceCardHistory({required String patientId}); + + Future>> getPatientInsuranceDetailsForUpdate({required String patientId, required String identificationNo}); } class InsuranceRepoImp implements InsuranceRepo { @@ -45,7 +51,7 @@ class InsuranceRepoImp implements InsuranceRepo { onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; }, - onSuccess: (response, statusCode, {messageStatus}) { + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { try { final list = response['List_PatientInsuranceCard']; if (list == null || list.isEmpty) { @@ -74,4 +80,123 @@ class InsuranceRepoImp implements InsuranceRepo { throw UnimplementedError(); } + + @override + Future>>> getPatientInsuranceCardHistory({required String patientId}) async { + final mapDevice = { + "isDentalAllowedBackend": false, + "VersionID": 50.0, + "Channel": 3, + "LanguageID": 2, + "IPAdress": "10.20.10.20", + "generalid": "Cs2020@2016\$2958", + "Latitude": 0.0, + "Longitude": 0.0, + "DeviceTypeID": 1, + "PatientType": 1, + "PatientTypeID": 1, + "TokenID": "@dm!n", + "PatientID": "3628599", + "PatientOutSA": "0", + "SessionID": "03478TYC02N80874CTYN04883475!?" + }; + + try { + GenericApiModel>? apiResponse; + Failure? failure; + await apiClient.post( + GET_PAtIENTS_INSURANCE_UPDATED, + body: mapDevice, + onFailure: (error, statusCode, {messageStatus, failureType}) { + failure = failureType; + }, + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { + try { + final list = response['List_PatientInsuranceCardHistory']; + if (list == null || list.isEmpty) { + throw Exception("insurance list is empty"); + } + + final insuranceCardsList = list.map((item) => PatientInsuranceCardHistoryResponseModel.fromJson(item as Map)).toList().cast(); + + apiResponse = GenericApiModel>( + messageStatus: messageStatus, + statusCode: statusCode, + errorMessage: null, + data: insuranceCardsList, + ); + } 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>> getPatientInsuranceDetailsForUpdate({required String patientId, required String identificationNo}) async { + final mapDevice = { + "SetupID": "010266", + "ProjectID": 15, + "PatientIdentificationID": "2464169354", + "isDentalAllowedBackend": false, + "PatientID": "3628599", + "IsFamily": false, + "ParentID": 0, + "VersionID": 18.8, + "Channel": 3, + "LanguageID": 2, + "IPAdress": "10.20.10.20", + "generalid": "Cs2020@2016\$2958", + "Latitude": 0.0, + "Longitude": 0.0, + "DeviceTypeID": 2, + "PatientType": 1, + "PatientTypeID": 1, + "TokenID": "@dm!n", + "PatientOutSA": 0, + "SessionID": "eyy7u090a9dfadsghfpsadiuhf234" + }; + + try { + GenericApiModel? apiResponse; + Failure? failure; + await apiClient.post( + GET_PATIENT_INSURANCE_DETAILS, + body: mapDevice, + onFailure: (error, statusCode, {messageStatus, failureType}) { + failure = failureType; + }, + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { + try { + final list = response['List_PatientInsuranceDetails']; + if (list == null || list.isEmpty) { + throw Exception("insurance list is empty"); + } + + final insuranceCardsList = PatientInsuranceUpdateResponseModel.fromJson(list[0]); + + apiResponse = GenericApiModel( + messageStatus: messageStatus, + statusCode: statusCode, + errorMessage: null, + data: insuranceCardsList, + ); + } 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/insurance/insurance_view_model.dart b/lib/features/insurance/insurance_view_model.dart index fac09da..169d967 100644 --- a/lib/features/insurance/insurance_view_model.dart +++ b/lib/features/insurance/insurance_view_model.dart @@ -1,24 +1,34 @@ import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/features/insurance/insurance_repo.dart'; +import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_card_history.dart'; import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_details_response_model.dart'; +import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_update_response_model.dart'; import 'package:hmg_patient_app_new/features/lab/lab_repo.dart'; import 'package:hmg_patient_app_new/services/error_handler_service.dart'; class InsuranceViewModel extends ChangeNotifier { bool isInsuranceLoading = false; bool isInsuranceHistoryLoading = false; + bool isInsuranceDetailsLoading = false; + bool isInsuranceUpdateDetailsLoading = false; InsuranceRepo insuranceRepo; ErrorHandlerService errorHandlerService; List patientInsuranceList = []; + List patientInsuranceCardHistoryList = []; + + PatientInsuranceUpdateResponseModel? patientInsuranceUpdateResponseModel; InsuranceViewModel({required this.insuranceRepo, required this.errorHandlerService}); initInsuranceProvider() { patientInsuranceList.clear(); + patientInsuranceCardHistoryList.clear(); isInsuranceLoading = true; isInsuranceHistoryLoading = true; + isInsuranceDetailsLoading = true; + isInsuranceUpdateDetailsLoading = true; getPatientInsuranceDetails(); notifyListeners(); } @@ -28,6 +38,16 @@ class InsuranceViewModel extends ChangeNotifier { notifyListeners(); } + setIsInsuranceDetailsLoading(bool val) { + isInsuranceDetailsLoading = val; + notifyListeners(); + } + + setIsInsuranceUpdateDetailsLoading(bool val) { + isInsuranceUpdateDetailsLoading = val; + notifyListeners(); + } + Future getPatientInsuranceDetails({Function(dynamic)? onSuccess, Function(String)? onError}) async { final result = await insuranceRepo.getPatientInsuranceDetails(patientId: "1231755"); @@ -47,4 +67,45 @@ class InsuranceViewModel extends ChangeNotifier { }, ); } + + Future getPatientInsuranceCardHistory({Function(dynamic)? onSuccess, Function(String)? onError}) async { + final result = await insuranceRepo.getPatientInsuranceCardHistory(patientId: "1231755"); + + 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) { + patientInsuranceCardHistoryList = apiResponse.data!; + patientInsuranceCardHistoryList = patientInsuranceCardHistoryList.take(3).toList(); + isInsuranceHistoryLoading = false; + notifyListeners(); + if (onSuccess != null) { + onSuccess(apiResponse); + } + } + }, + ); + } + + Future getPatientInsuranceDetailsForUpdate({Function(dynamic)? onSuccess, Function(String)? onError}) async { + final result = await insuranceRepo.getPatientInsuranceDetailsForUpdate(patientId: "1231755", identificationNo: ""); + + 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) { + patientInsuranceUpdateResponseModel = apiResponse.data!; + isInsuranceUpdateDetailsLoading = false; + notifyListeners(); + if (onSuccess != null) { + onSuccess(apiResponse); + } + } + }, + ); + } } diff --git a/lib/features/insurance/models/resp_models/patient_insurance_card_history.dart b/lib/features/insurance/models/resp_models/patient_insurance_card_history.dart new file mode 100644 index 0000000..17436f0 --- /dev/null +++ b/lib/features/insurance/models/resp_models/patient_insurance_card_history.dart @@ -0,0 +1,73 @@ +class PatientInsuranceCardHistoryResponseModel { + int? createdBy; + String? createdOn; + int? editedBy; + String? editedOn; + String? insuranceCardImage; + String? mobileNumber; + int? patientID; + String? patientIdentificationNo; + String? patientInsuranceCardUpdateInfoID; + int? patientType; + int? projectID; + String? rejectionRemarks; + int? setupID; + int? status; + String? statusDescription; + + PatientInsuranceCardHistoryResponseModel( + {this.createdBy, + this.createdOn, + this.editedBy, + this.editedOn, + this.insuranceCardImage, + this.mobileNumber, + this.patientID, + this.patientIdentificationNo, + this.patientInsuranceCardUpdateInfoID, + this.patientType, + this.projectID, + this.rejectionRemarks, + this.setupID, + this.status, + this.statusDescription}); + + PatientInsuranceCardHistoryResponseModel.fromJson(Map json) { + createdBy = json['CreatedBy']; + createdOn = json['CreatedOn']; + editedBy = json['EditedBy']; + editedOn = json['EditedOn']; + insuranceCardImage = json['InsuranceCardImage']; + mobileNumber = json['MobileNumber']; + patientID = json['PatientID']; + patientIdentificationNo = json['PatientIdentificationNo']; + patientInsuranceCardUpdateInfoID = json['PatientInsuranceCardUpdateInfoID']; + patientType = json['PatientType']; + projectID = json['ProjectID']; + rejectionRemarks = json['RejectionRemarks']; + setupID = json['SetupID']; + status = json['Status']; + statusDescription = json['StatusDescription']; + } + + Map toJson() { + final Map data = new Map(); + data['CreatedBy'] = this.createdBy; + data['CreatedOn'] = this.createdOn; + data['EditedBy'] = this.editedBy; + data['EditedOn'] = this.editedOn; + data['InsuranceCardImage'] = this.insuranceCardImage; + data['MobileNumber'] = this.mobileNumber; + data['PatientID'] = this.patientID; + data['PatientIdentificationNo'] = this.patientIdentificationNo; + data['PatientInsuranceCardUpdateInfoID'] = + this.patientInsuranceCardUpdateInfoID; + data['PatientType'] = this.patientType; + data['ProjectID'] = this.projectID; + data['RejectionRemarks'] = this.rejectionRemarks; + data['SetupID'] = this.setupID; + data['Status'] = this.status; + data['StatusDescription'] = this.statusDescription; + return data; + } +} diff --git a/lib/features/insurance/models/resp_models/patient_insurance_update_response_model.dart b/lib/features/insurance/models/resp_models/patient_insurance_update_response_model.dart new file mode 100644 index 0000000..3903a99 --- /dev/null +++ b/lib/features/insurance/models/resp_models/patient_insurance_update_response_model.dart @@ -0,0 +1,88 @@ +class PatientInsuranceUpdateResponseModel { + dynamic approvalLimit; + int? companyGroupID; + String? companyName; + String? companyRemarks; + String? dOB; + dynamic deductible; + String? effectiveFrom; + String? effectiveTo; + String? eligabilityFailureReason; + bool? isMemberEligible; + String? memberID; + String? memberName; + String? memberStatus; + dynamic message; + String? nationalId; + String? policyNumber; + String? responseMessage; + dynamic room; + String? subCategory; + + PatientInsuranceUpdateResponseModel( + {this.approvalLimit, + this.companyGroupID, + this.companyName, + this.companyRemarks, + this.dOB, + this.deductible, + this.effectiveFrom, + this.effectiveTo, + this.eligabilityFailureReason, + this.isMemberEligible, + this.memberID, + this.memberName, + this.memberStatus, + this.message, + this.nationalId, + this.policyNumber, + this.responseMessage, + this.room, + this.subCategory}); + + PatientInsuranceUpdateResponseModel.fromJson(Map json) { + approvalLimit = json['ApprovalLimit']; + companyGroupID = json['CompanyGroupID']; + companyName = json['CompanyName']; + companyRemarks = json['CompanyRemarks']; + dOB = json['DOB']; + deductible = json['Deductible']; + effectiveFrom = json['EffectiveFrom']; + effectiveTo = json['EffectiveTo']; + eligabilityFailureReason = json['EligabilityFailureReason']; + isMemberEligible = json['IsMemberEligible']; + memberID = json['MemberID']; + memberName = json['MemberName']; + memberStatus = json['MemberStatus']; + message = json['Message']; + nationalId = json['NationalId']; + policyNumber = json['PolicyNumber']; + responseMessage = json['ResponseMessage']; + room = json['Room']; + subCategory = json['SubCategory']; + } + + Map toJson() { + final Map data = new Map(); + data['ApprovalLimit'] = this.approvalLimit; + data['CompanyGroupID'] = this.companyGroupID; + data['CompanyName'] = this.companyName; + data['CompanyRemarks'] = this.companyRemarks; + data['DOB'] = this.dOB; + data['Deductible'] = this.deductible; + data['EffectiveFrom'] = this.effectiveFrom; + data['EffectiveTo'] = this.effectiveTo; + data['EligabilityFailureReason'] = this.eligabilityFailureReason; + data['IsMemberEligible'] = this.isMemberEligible; + data['MemberID'] = this.memberID; + data['MemberName'] = this.memberName; + data['MemberStatus'] = this.memberStatus; + data['Message'] = this.message; + data['NationalId'] = this.nationalId; + data['PolicyNumber'] = this.policyNumber; + data['ResponseMessage'] = this.responseMessage; + data['Room'] = this.room; + data['SubCategory'] = this.subCategory; + return data; + } +} diff --git a/lib/features/lab/lab_repo.dart b/lib/features/lab/lab_repo.dart index 326379c..d746c69 100644 --- a/lib/features/lab/lab_repo.dart +++ b/lib/features/lab/lab_repo.dart @@ -45,7 +45,7 @@ class LabRepoImp implements LabRepo { onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; }, - onSuccess: (response, statusCode, {messageStatus}) { + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { try { final list = response['ListPLO']; if (list == null || list.isEmpty) { diff --git a/lib/features/prescriptions/prescriptions_repo.dart b/lib/features/prescriptions/prescriptions_repo.dart index de7bc4b..f584f7b 100644 --- a/lib/features/prescriptions/prescriptions_repo.dart +++ b/lib/features/prescriptions/prescriptions_repo.dart @@ -48,7 +48,7 @@ class PrescriptionsRepoImp implements PrescriptionsRepo { onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; }, - onSuccess: (response, statusCode, {messageStatus}) { + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { try { final list = response['PatientPrescriptionList']; if (list == null || list.isEmpty) { @@ -111,7 +111,7 @@ class PrescriptionsRepoImp implements PrescriptionsRepo { onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; }, - onSuccess: (response, statusCode, {messageStatus}) { + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { try { final list = prescriptionsResponseModel.isInOutPatient! ? response['ListPRM'] : response['INP_GetPrescriptionReport_List']; if (list == null || list.isEmpty) { diff --git a/lib/features/radiology/radiology_repo.dart b/lib/features/radiology/radiology_repo.dart index d3e4f3d..2917dfd 100644 --- a/lib/features/radiology/radiology_repo.dart +++ b/lib/features/radiology/radiology_repo.dart @@ -1,8 +1,8 @@ +import 'package:dartz/dartz.dart'; import 'package:hmg_patient_app_new/core/api/api_client.dart'; import 'package:hmg_patient_app_new/core/api_consts.dart'; -import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart'; import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart'; -import 'package:dartz/dartz.dart'; +import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart'; import 'package:hmg_patient_app_new/features/radiology/models/resp_models/patient_radiology_response_model.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart'; @@ -45,7 +45,7 @@ class RadiologyRepoImp implements RadiologyRepo { onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; }, - onSuccess: (response, statusCode, {messageStatus}) { + onSuccess: (response, statusCode, {messageStatus, errorMessage}) { final radOrders; try { if (response['FinalRadiologyList'] != null && response['FinalRadiologyList'].length != 0) { diff --git a/lib/main.dart b/lib/main.dart index ce69f5d..53825c8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,7 +5,9 @@ import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; +import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart'; import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart'; import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart'; @@ -34,6 +36,16 @@ class MyHttpOverrides extends HttpOverrides { } } +Future callAppStateInitializations() async { + final String deviceTypeId = (Platform.isIOS + ? "1" + : await Utils.isGoogleServicesAvailable() + ? "2" + : "3"); + AppState appState = getIt.get(); + appState.setDeviceTypeID = deviceTypeId; +} + Future callInitializations() async { WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); @@ -41,6 +53,7 @@ Future callInitializations() async { AppDependencies.addDependencies(); SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); HttpOverrides.global = MyHttpOverrides(); + await callAppStateInitializations(); } void main() async { @@ -84,6 +97,8 @@ void main() async { appState: getIt(), dialogService: getIt(), errorHandlerService: getIt(), + navigationService: getIt(), + cacheService: getIt(), ), ), ], child: MyApp()), diff --git a/lib/presentation/authentication/login.dart b/lib/presentation/authentication/login.dart index aef877f..f6e725a 100644 --- a/lib/presentation/authentication/login.dart +++ b/lib/presentation/authentication/login.dart @@ -1,7 +1,10 @@ +import 'dart:developer'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; +import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/context_extensions.dart'; @@ -18,11 +21,13 @@ import 'package:hmg_patient_app_new/widgets/input_widget.dart'; import 'package:provider/provider.dart'; class LoginScreen extends StatefulWidget { + const LoginScreen({super.key}); + @override - _LoginScreen createState() => _LoginScreen(); + LoginScreenState createState() => LoginScreenState(); } -class _LoginScreen extends State { +class LoginScreenState extends State { @override void initState() { super.initState(); @@ -83,7 +88,7 @@ class _LoginScreen extends State { icon: AppAssets.login1, iconColor: Colors.white, onPressed: () { - showLoginModel(context: context, authVM: authVm); + showLoginModelSheet(context: context, phoneNumberController: authVm.phoneNumberController, authViewModel: authVm); // if (nationIdController.text.isNotEmpty) { // } else { @@ -140,29 +145,35 @@ class _LoginScreen extends State { ); } - void showLoginModel({required BuildContext context, required AuthenticationViewModel authVM}) { + void showLoginModelSheet({ + required BuildContext context, + required TextEditingController? phoneNumberController, + required AuthenticationViewModel authViewModel, + }) { context.showBottomSheet( isScrollControlled: true, isDismissible: false, useSafeArea: true, - backgroundColor: Colors.transparent, + backgroundColor: AppColors.transparent, child: StatefulBuilder(builder: (BuildContext context, StateSetter setModalState) { return Padding( padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), child: SingleChildScrollView( child: GenericBottomSheet( - countryCode: authVM.selectedCountrySignup.countryCode, + countryCode: authViewModel.selectedCountrySignup.countryCode, initialPhoneNumber: "", - textController: authVM.phoneNumberController, + textController: phoneNumberController, isEnableCountryDropdown: true, - onCountryChange: authVM.onCountryChange, - onChange: authVM.onPhoneNumberChange, + onCountryChange: authViewModel.onCountryChange, + onChange: authViewModel.onPhoneNumberChange, buttons: [ Padding( padding: EdgeInsets.only(bottom: 10.h), child: CustomButton( text: LocaleKeys.sendOTPSMS.tr(), - onPressed: () {}, + onPressed: () async { + await authViewModel.checkUserAuthentication(otpTypeEnum: OTPTypeEnum.sms); + }, backgroundColor: AppColors.primaryRedColor, borderColor: AppColors.primaryRedBorderColor, textColor: AppColors.whiteColor, @@ -183,7 +194,11 @@ class _LoginScreen extends State { padding: EdgeInsets.only(bottom: 10.h, top: 10.h), child: CustomButton( text: LocaleKeys.sendOTPWHATSAPP.tr(), - onPressed: () {}, + onPressed: () async { + log("phoneNumberController: ${phoneNumberController == null}"); + log("phoneNumberControllerVa: ${phoneNumberController?.text}"); + await authViewModel.checkUserAuthentication(otpTypeEnum: OTPTypeEnum.whatsapp); + }, backgroundColor: Colors.white, borderColor: AppColors.borderOnlyColor, textColor: AppColors.textColor, diff --git a/lib/presentation/authentication/register.dart b/lib/presentation/authentication/register.dart index 4756cba..e51792c 100644 --- a/lib/presentation/authentication/register.dart +++ b/lib/presentation/authentication/register.dart @@ -10,15 +10,14 @@ 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/widgets/otp_verification_screen.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/appbar/app_bar_widget.dart'; import 'package:hmg_patient_app_new/widgets/bottomsheet/generic_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart' show CustomButton; import 'package:hmg_patient_app_new/widgets/dropdown/country_dropdown_widget.dart'; -import 'package:hmg_patient_app_new/widgets/dropdown/dropdown_widget.dart'; import 'package:hmg_patient_app_new/widgets/input_widget.dart'; -import 'package:hmg_patient_app_new/widgets/otp/otp.dart'; import 'package:provider/provider.dart'; class RegisterNew extends StatefulWidget { @@ -225,9 +224,12 @@ class _RegisterNew extends State { text: LocaleKeys.sendOTPSMS.tr(), onPressed: () { Navigator.of(context).push(MaterialPageRoute( - builder: (BuildContext context) => OTPVerificationPage( - phoneNumber: '12234567', - ))); + builder: (BuildContext context) => OTPVerificationScreen( + phoneNumber: '504278212', + checkActivationCode: (int code) {}, + onResendOTPPressed: (String phone) {}, + ), + )); // if (mobileNo.isEmpty) { // context.showBottomSheet( @@ -252,7 +254,6 @@ class _RegisterNew extends State { // } else { // registerUser(1); // } - Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => OTPVerificationPage(phoneNumber: '12234567'))); }, backgroundColor: AppColors.primaryRedColor, borderColor: AppColors.primaryRedBorderColor, diff --git a/lib/presentation/authentication/register_step2.dart b/lib/presentation/authentication/register_step2.dart index 483ce5c..151a4c8 100644 --- a/lib/presentation/authentication/register_step2.dart +++ b/lib/presentation/authentication/register_step2.dart @@ -1,15 +1,11 @@ -import 'dart:convert'; - import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:get_it/get_it.dart'; 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/common_models/nationality_country_model.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/enums.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; -import 'package:hmg_patient_app_new/extensions/context_extensions.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'; @@ -112,8 +108,8 @@ class _RegisterNew extends State { labelText: LocaleKeys.gender.tr(), hintText: LocaleKeys.malE.tr(), isEnable: true, - dropdownItems: GenderTypeEnum.values.map((e) => appState!.isArabic() ? e.typeAr : e.type).toList(), - selectedValue: genderType != null ? (appState!.isArabic() ? genderType!.typeAr : genderType!.type) : "", + dropdownItems: GenderTypeEnum.values.map((e) => appState.isArabic() ? e.typeAr : e.type).toList(), + selectedValue: genderType != null ? (appState.isArabic() ? genderType.typeAr : genderType.type) : "", onChange: authVM.onGenderChange, isBorderAllowed: false, hasSelectionCustomIcon: true, @@ -147,8 +143,8 @@ class _RegisterNew extends State { labelText: LocaleKeys.maritalStatus.tr(), hintText: LocaleKeys.married.tr(), isEnable: true, - dropdownItems: MaritalStatusTypeEnum.values.map((e) => appState!.isArabic() ? e.typeAr : e.type).toList(), - selectedValue: maritalStatus != null ? (appState!.isArabic() ? maritalStatus.typeAr : maritalStatus.type) : "", + dropdownItems: MaritalStatusTypeEnum.values.map((e) => appState.isArabic() ? e.typeAr : e.type).toList(), + selectedValue: maritalStatus != null ? (appState.isArabic() ? maritalStatus.typeAr : maritalStatus.type) : "", onChange: authVM.onMaritalStatusChange, isBorderAllowed: false, hasSelectionCustomIcon: true, @@ -161,7 +157,7 @@ class _RegisterNew extends State { ) : TextInputWidget( labelText: LocaleKeys.maritalStatus.tr(), - hintText: appState!.isArabic() + hintText: appState.isArabic() ? (MaritalStatusTypeExtension.fromValue(widget.nHICData!.maritalStatusCode)!.typeAr) : (MaritalStatusTypeExtension.fromValue(widget.nHICData!.maritalStatusCode)!.type), isEnable: true, @@ -178,7 +174,11 @@ class _RegisterNew extends State { ? Selector? countriesList, NationalityCountries? selectedCountry, bool isArabic})>( selector: (context, authViewModel) { final appState = getIt.get(); - return (countriesList: authViewModel.countriesList, selectedCountry: authViewModel.pickedCountryByUAEUser, isArabic: appState.isArabic()); + return ( + countriesList: authViewModel.countriesList, + selectedCountry: authViewModel.pickedCountryByUAEUser, + isArabic: appState.isArabic(), + ); }, shouldRebuild: (previous, next) => previous.countriesList != next.countriesList || previous.selectedCountry != next.selectedCountry || previous.isArabic != next.isArabic, builder: (context, data, child) { diff --git a/lib/presentation/home/data/landing_page_data.dart b/lib/presentation/home/data/landing_page_data.dart index 8474422..ad524e3 100644 --- a/lib/presentation/home/data/landing_page_data.dart +++ b/lib/presentation/home/data/landing_page_data.dart @@ -1,5 +1,3 @@ -import 'dart:ui'; - import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/presentation/home/data/service_card_data.dart'; diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index db21b9e..fdeb407 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -11,14 +11,15 @@ import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; -import 'package:hmg_patient_app_new/presentation/authentication/login.dart'; import 'package:hmg_patient_app_new/presentation/home/data/landing_page_data.dart'; import 'package:hmg_patient_app_new/presentation/home/widgets/habib_wallet_card.dart'; import 'package:hmg_patient_app_new/presentation/home/widgets/large_service_card.dart'; import 'package:hmg_patient_app_new/presentation/home/widgets/small_service_card.dart'; import 'package:hmg_patient_app_new/presentation/medical_file/medical_file_page.dart'; +import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; +import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart' show CustomTabBar; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:provider/provider.dart'; @@ -30,246 +31,246 @@ class LandingPage extends StatefulWidget { } class _LandingPageState extends State { - @override Widget build(BuildContext context) { AppState appState = getIt.get(); + NavigationService navigationService = getIt.get(); final AuthenticationViewModel authenticationViewModel = context.read(); return Scaffold( backgroundColor: AppColors.bgScaffoldColor, - body: Padding( - padding: EdgeInsets.all(24.h), - child: SingleChildScrollView( - child: Column( - children: [ - Padding( - padding: EdgeInsets.only(top: 50.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - CustomButton( - text: LocaleKeys.loginOrRegister.tr(context: context), - onPressed: () async { - // await authenticationViewModel.selectDeviceImei(); - Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => LoginScreen())); - }, - backgroundColor: Color(0xffFEE9EA), - borderColor: Color(0xffFEE9EA), - textColor: Color(0xffED1C2B), - fontSize: 16, - fontWeight: FontWeight.w500, - borderRadius: 12, - padding: EdgeInsets.fromLTRB(10, 0, 10, 0), - height: 50, - ), - Utils.buildSvgWithAssets( - icon: AppAssets.contact_icon, - width: 24, - height: 24, - ).onPress(() { - Navigator.of(context).push( - FadePage( - page: MedicalFilePage(), - // page: LoginScreen(), + body: SingleChildScrollView( + child: Column( + children: [ + Padding( + padding: EdgeInsets.only(top: 50.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + CustomButton( + text: LocaleKeys.loginOrRegister.tr(context: context), + onPressed: () async { + await authenticationViewModel.onLoginPressed(); + }, + backgroundColor: Color(0xffFEE9EA), + borderColor: Color(0xffFEE9EA), + textColor: Color(0xffED1C2B), + fontSize: 16, + fontWeight: FontWeight.w500, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 50, + ), + Utils.buildSvgWithAssets( + icon: AppAssets.contact_icon, + width: 24, + height: 24, + ).onPress(() { + Navigator.of(context).push( + FadePage( + page: MedicalFilePage(), + // page: LoginScreen(), + ), + ); + }), + ], + ).paddingSymmetrical(24.h, 0.h), + ), + SizedBox(height: 16.h), + appState.isAuthenticated + ? Column( + children: [ + Container( + width: double.infinity, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24, ), - ); - }), - ], - ), - ), - SizedBox(height: 16.h), - appState.isAuthenticated - ? Column( - children: [ - Container( - width: double.infinity, - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 24, - ), - child: Padding( - padding: EdgeInsets.all(12.h), - child: Column( - children: [ - Utils.buildSvgWithAssets(icon: AppAssets.home_calendar_icon, width: 32.h, height: 32.h), - SizedBox(height: 12.h), - "You do not have any upcoming appointment. Please book an appointment".toText12(isCenter: true), - SizedBox(height: 12.h), - CustomButton( - text: LocaleKeys.bookAppo.tr(context: context), - onPressed: () { - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (BuildContext context) => LandingPage()), - ); - }, - backgroundColor: Color(0xffFEE9EA), - borderColor: Color(0xffFEE9EA), - textColor: Color(0xffED1C2B), - fontSize: 14, - fontWeight: FontWeight.w500, - borderRadius: 12, - padding: EdgeInsets.fromLTRB(10, 0, 10, 0), - height: 40, - icon: AppAssets.add_icon, - iconColor: AppColors.primaryRedColor, - ), - ], - ), + child: Padding( + padding: EdgeInsets.all(12.h), + child: Column( + children: [ + Utils.buildSvgWithAssets(icon: AppAssets.home_calendar_icon, width: 32.h, height: 32.h), + SizedBox(height: 12.h), + "You do not have any upcoming appointment. Please book an appointment".toText12(isCenter: true), + SizedBox(height: 12.h), + CustomButton( + text: LocaleKeys.bookAppo.tr(context: context), + onPressed: () { + Navigator.of(context).pushReplacement( + MaterialPageRoute(builder: (BuildContext context) => LandingPage()), + ); + }, + backgroundColor: Color(0xffFEE9EA), + borderColor: Color(0xffFEE9EA), + textColor: Color(0xffED1C2B), + fontSize: 14, + fontWeight: FontWeight.w500, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 40, + icon: AppAssets.add_icon, + iconColor: AppColors.primaryRedColor, + ), + ], ), ), - SizedBox(height: 12.h), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - "Quick Links".toText16(isBold: true), - Row( - children: [ - "View medical file".toText12(color: AppColors.primaryRedColor), - SizedBox(width: 2.h), - Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), - ], - ), - ], - ), - SizedBox(height: 12.h), - Container( - height: 127.h, - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 24, + ).paddingSymmetrical(24.h, 0.h), + SizedBox(height: 12.h), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "Quick Links".toText16(isBold: true), + Row( + children: [ + "View medical file".toText12(color: AppColors.primaryRedColor), + SizedBox(width: 2.h), + Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), + ], ), - child: Padding( - padding: EdgeInsets.all(16.h), - child: Column( - children: [ - Expanded( - child: ListView.separated( - scrollDirection: Axis.horizontal, - itemCount: LandingPageData.getLoggedInServiceCardsList.length, - shrinkWrap: true, - padding: const EdgeInsets.only(left: 0, right: 8), - itemBuilder: (context, index) { - return AnimationConfiguration.staggeredList( - position: index, - duration: const Duration(milliseconds: 1000), - child: SlideAnimation( - horizontalOffset: 100.0, - child: FadeInAnimation( - child: SmallServiceCard( - serviceName: LandingPageData.getLoggedInServiceCardsList[index].serviceName, - icon: LandingPageData.getLoggedInServiceCardsList[index].icon, - title: LandingPageData.getLoggedInServiceCardsList[index].title, - subtitle: LandingPageData.getLoggedInServiceCardsList[index].subtitle, - iconColor: LandingPageData.getLoggedInServiceCardsList[index].iconColor, - textColor: LandingPageData.getLoggedInServiceCardsList[index].textColor, - backgroundColor: LandingPageData.getLoggedInServiceCardsList[index].backgroundColor, - isBold: LandingPageData.getLoggedInServiceCardsList[index].isBold, - ), + ], + ).paddingSymmetrical(24.h, 0.h), + SizedBox(height: 12.h), + Container( + height: 127.h, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24, + ), + child: Padding( + padding: EdgeInsets.all(16.h), + child: Column( + children: [ + Expanded( + child: ListView.separated( + scrollDirection: Axis.horizontal, + itemCount: LandingPageData.getLoggedInServiceCardsList.length, + shrinkWrap: true, + padding: const EdgeInsets.only(left: 0, right: 8), + itemBuilder: (context, index) { + return AnimationConfiguration.staggeredList( + position: index, + duration: const Duration(milliseconds: 1000), + child: SlideAnimation( + horizontalOffset: 100.0, + child: FadeInAnimation( + child: SmallServiceCard( + icon: LandingPageData.getLoggedInServiceCardsList[index].icon, + title: LandingPageData.getLoggedInServiceCardsList[index].title, + subtitle: LandingPageData.getLoggedInServiceCardsList[index].subtitle, + iconColor: LandingPageData.getLoggedInServiceCardsList[index].iconColor, + textColor: LandingPageData.getLoggedInServiceCardsList[index].textColor, + backgroundColor: LandingPageData.getLoggedInServiceCardsList[index].backgroundColor, + isBold: LandingPageData.getLoggedInServiceCardsList[index].isBold, + serviceName: LandingPageData.getLoggedInServiceCardsList[index].serviceName, ), ), - ); - }, - separatorBuilder: (BuildContext cxt, int index) => 0.width, - ), + ), + ); + }, + separatorBuilder: (BuildContext cxt, int index) => 0.width, ), - ], - ), + ), + ], ), - ) - ], - ) - : Container( - height: 127.h, - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24), - child: Padding( - padding: EdgeInsets.all(16.h), - child: Column( - children: [ - Expanded( - child: ListView.separated( - scrollDirection: Axis.horizontal, - itemCount: LandingPageData.getNotLoggedInServiceCardsList.length, - shrinkWrap: true, - padding: const EdgeInsets.only(left: 0, right: 8), - itemBuilder: (context, index) { - return AnimationConfiguration.staggeredList( - position: index, - duration: const Duration(milliseconds: 1000), - child: SlideAnimation( - horizontalOffset: 100.0, - child: FadeInAnimation( - child: SmallServiceCard( - icon: LandingPageData.getNotLoggedInServiceCardsList[index].icon, - title: LandingPageData.getNotLoggedInServiceCardsList[index].title, - subtitle: LandingPageData.getNotLoggedInServiceCardsList[index].subtitle, - iconColor: LandingPageData.getNotLoggedInServiceCardsList[index].iconColor, - textColor: LandingPageData.getNotLoggedInServiceCardsList[index].textColor, - backgroundColor: LandingPageData.getNotLoggedInServiceCardsList[index].backgroundColor, - isBold: LandingPageData.getNotLoggedInServiceCardsList[index].isBold, - ), + ), + ).paddingSymmetrical(24.h, 0.h), + ], + ) + : Container( + height: 127.h, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24, + ), + child: Padding( + padding: EdgeInsets.all(16.h), + child: Column( + children: [ + Expanded( + child: ListView.separated( + scrollDirection: Axis.horizontal, + itemCount: LandingPageData.getNotLoggedInServiceCardsList.length, + shrinkWrap: true, + padding: const EdgeInsets.only(left: 0, right: 8), + itemBuilder: (context, index) { + return AnimationConfiguration.staggeredList( + position: index, + duration: const Duration(milliseconds: 1000), + child: SlideAnimation( + horizontalOffset: 100.0, + child: FadeInAnimation( + child: SmallServiceCard( + icon: LandingPageData.getNotLoggedInServiceCardsList[index].icon, + title: LandingPageData.getNotLoggedInServiceCardsList[index].title, + subtitle: LandingPageData.getNotLoggedInServiceCardsList[index].subtitle, + iconColor: LandingPageData.getNotLoggedInServiceCardsList[index].iconColor, + textColor: LandingPageData.getNotLoggedInServiceCardsList[index].textColor, + backgroundColor: LandingPageData.getNotLoggedInServiceCardsList[index].backgroundColor, + isBold: LandingPageData.getNotLoggedInServiceCardsList[index].isBold, ), ), - ); - }, - separatorBuilder: (BuildContext cxt, int index) => 0.width, - ), + ), + ); + }, + separatorBuilder: (BuildContext cxt, int index) => 0.width, ), - ], - ), + ), + ], ), ), - SizedBox(height: 16.h), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - "Services".toText16(isBold: true), - Row( - children: [ - "View all services".toText12(color: AppColors.primaryRedColor), - SizedBox(width: 2.h), - Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), - ], - ), - ], - ), - SizedBox(height: 16.h), - SizedBox( - height: 325.h, - child: Column( + ).paddingSymmetrical(24.h, 0.h), + SizedBox(height: 16.h), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "Services".toText16(isBold: true), + Row( children: [ - Expanded( - child: ListView.separated( - scrollDirection: Axis.horizontal, - itemCount: LandingPageData.getServiceCardsList.length, - shrinkWrap: true, - padding: const EdgeInsets.only(left: 0, right: 8), - itemBuilder: (context, index) { - return AnimationConfiguration.staggeredList( - position: index, - duration: const Duration(milliseconds: 1000), - child: SlideAnimation( - horizontalOffset: 100.0, - child: FadeInAnimation( - child: LargeServiceCard( - image: LandingPageData.getServiceCardsList[index].icon, - title: LandingPageData.getServiceCardsList[index].title, - subtitle: LandingPageData.getServiceCardsList[index].subtitle, - icon: LandingPageData.getServiceCardsList[index].largeCardIcon, - ), + "View all services".toText12(color: AppColors.primaryRedColor), + SizedBox(width: 2.h), + Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), + ], + ), + ], + ).paddingSymmetrical(24.h, 0.h), + SizedBox(height: 16.h), + SizedBox( + height: 325.h, + child: Column( + children: [ + Expanded( + child: ListView.separated( + scrollDirection: Axis.horizontal, + itemCount: LandingPageData.getServiceCardsList.length, + shrinkWrap: true, + padding: const EdgeInsets.only(left: 0, right: 8), + itemBuilder: (context, index) { + return AnimationConfiguration.staggeredList( + position: index, + duration: const Duration(milliseconds: 1000), + child: SlideAnimation( + horizontalOffset: 100.0, + child: FadeInAnimation( + child: LargeServiceCard( + image: LandingPageData.getServiceCardsList[index].icon, + title: LandingPageData.getServiceCardsList[index].title, + subtitle: LandingPageData.getServiceCardsList[index].subtitle, + icon: LandingPageData.getServiceCardsList[index].largeCardIcon, ), ), - ); - }, - separatorBuilder: (BuildContext cxt, int index) => 0.width, - ), + ), + ); + }, + separatorBuilder: (BuildContext cxt, int index) => 0.width, ), - ], - ), + ), + ], ), - SizedBox(height: 16.h), - appState.isAuthenticated ? HabibWalletCard() : SizedBox(), - ], - ), + ), + SizedBox(height: 16.h), + appState.isAuthenticated ? HabibWalletCard() : SizedBox(), + SizedBox(height: 16.h), + ], ), ), ); diff --git a/lib/presentation/home/widgets/habib_wallet_card.dart b/lib/presentation/home/widgets/habib_wallet_card.dart index 9b513db..80855dd 100644 --- a/lib/presentation/home/widgets/habib_wallet_card.dart +++ b/lib/presentation/home/widgets/habib_wallet_card.dart @@ -26,7 +26,7 @@ class HabibWalletCard extends StatelessWidget { ], ), ], - ), + ).paddingSymmetrical(24.h, 0.h), SizedBox(height: 16.h), Container( // height: 150.h, @@ -120,7 +120,7 @@ class HabibWalletCard extends StatelessWidget { ), ), ]), - ) + ).paddingSymmetrical(24.h, 0.h), ], ); } diff --git a/lib/presentation/insurance/insurance_home_page.dart b/lib/presentation/insurance/insurance_home_page.dart index 920e589..131c454 100644 --- a/lib/presentation/insurance/insurance_home_page.dart +++ b/lib/presentation/insurance/insurance_home_page.dart @@ -62,8 +62,9 @@ class _InsuranceHomePageState extends State { text: LocaleKeys.history.tr(context: context), onPressed: () { insuranceVM.setIsInsuranceHistoryLoading(true); + insuranceVM.getPatientInsuranceCardHistory(); showCommonBottomSheet(context, - child: InsuranceHistory(), title: "", height: ResponsiveExtension.screenHeight * 0.5, isCloseButtonVisible: false, isFullScreen: false); + child: InsuranceHistory(), callBackFunc: () {}, title: "", height: ResponsiveExtension.screenHeight * 0.65, isCloseButtonVisible: false, isFullScreen: false); }, backgroundColor: AppColors.primaryRedColor.withOpacity(0.1), borderColor: AppColors.primaryRedColor.withOpacity(0.0), diff --git a/lib/presentation/insurance/widgets/insurance_history.dart b/lib/presentation/insurance/widgets/insurance_history.dart index 0708c7c..397cb63 100644 --- a/lib/presentation/insurance/widgets/insurance_history.dart +++ b/lib/presentation/insurance/widgets/insurance_history.dart @@ -1,5 +1,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; @@ -7,6 +8,8 @@ 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/insurance/insurance_view_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart'; +import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart'; import 'package:provider/provider.dart'; @@ -31,7 +34,100 @@ class InsuranceHistory extends StatelessWidget { }), ], ).paddingSymmetrical(24.h, 24.h), - insuranceVM.isInsuranceHistoryLoading ? const MoviesShimmerWidget().paddingSymmetrical(24.h, 24.h) : Container() + insuranceVM.isInsuranceHistoryLoading + ? const MoviesShimmerWidget().paddingSymmetrical(24.h, 24.h) + : ListView.separated( + itemCount: insuranceVM.patientInsuranceCardHistoryList.length, + shrinkWrap: true, + padding: const EdgeInsets.only(left: 0, right: 8), + itemBuilder: (context, index) { + return AnimationConfiguration.staggeredList( + position: index, + duration: const Duration(milliseconds: 1000), + child: SlideAnimation( + verticalOffset: 100.0, + child: FadeInAnimation( + child: Container( + // height: 120.h, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + CustomButton( + text: insuranceVM.patientInsuranceCardHistoryList[index].statusDescription!, + onPressed: () {}, + backgroundColor: AppColors.primaryRedColor.withOpacity(0.1), + borderColor: AppColors.primaryRedColor.withOpacity(0.0), + textColor: AppColors.primaryRedColor, + fontSize: 10, + fontWeight: FontWeight.w500, + borderRadius: 8, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 30.h, + ), + ], + ), + SizedBox(height: 8.h), + "Haroon Amjad".toText16(weight: FontWeight.w600), + SizedBox(height: 8.h), + Row( + children: [ + Wrap( + direction: Axis.horizontal, + spacing: 4.h, + runSpacing: 4.h, + children: [ + Row( + children: [ + CustomButton( + text: "File No.: 3628599", + onPressed: () {}, + backgroundColor: AppColors.greyColor, + borderColor: AppColors.greyColor, + textColor: AppColors.blackColor, + fontSize: 10, + fontWeight: FontWeight.w500, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 30.h, + ), + ], + ), + Row( + children: [ + CustomButton( + text: insuranceVM.patientInsuranceCardHistoryList[index].createdOn!, + // text: "test", + onPressed: () {}, + backgroundColor: AppColors.greyColor, + borderColor: AppColors.greyColor, + textColor: AppColors.blackColor, + fontSize: 10, + fontWeight: FontWeight.w500, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 30.h, + ), + ], + ), + ], + ), + ], + ), + ], + ).paddingSymmetrical(16.h, 16.h), + ).paddingSymmetrical(24.h, 0.h), + ), + ), + ); + }, + separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h), + ), ], ); }); diff --git a/lib/presentation/insurance/widgets/insurance_update_details_card.dart b/lib/presentation/insurance/widgets/insurance_update_details_card.dart new file mode 100644 index 0000000..51afdc4 --- /dev/null +++ b/lib/presentation/insurance/widgets/insurance_update_details_card.dart @@ -0,0 +1,139 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:hmg_patient_app_new/core/app_assets.dart'; +import 'package:hmg_patient_app_new/core/utils/date_util.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/insurance/insurance_view_model.dart'; +import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart'; +import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; +import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart'; +import 'package:provider/provider.dart'; + +class PatientInsuranceCardUpdateCard extends StatelessWidget { + PatientInsuranceCardUpdateCard({super.key}); + + late InsuranceViewModel insuranceViewModel; + + @override + Widget build(BuildContext context) { + insuranceViewModel = Provider.of(context); + return Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + LocaleKeys.insuranceCards.tr(context: context).toText24(isBold: true), + Utils.buildSvgWithAssets(icon: AppAssets.close_bottom_sheet_icon).onPress(() { + Navigator.of(context).pop(); + }), + ], + ).paddingSymmetrical(24.h, 24.h), + insuranceViewModel.isInsuranceUpdateDetailsLoading + ? const MoviesShimmerWidget().paddingSymmetrical(24.h, 24.h) + : Container( + // height: 120.h, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Haroon Amjad".toText16(weight: FontWeight.w600), + "Policy: ${insuranceViewModel.patientInsuranceUpdateResponseModel!.policyNumber}".toText12(isBold: true, color: AppColors.lightGrayColor), + SizedBox(height: 8.h), + Row( + children: [ + insuranceViewModel.patientInsuranceUpdateResponseModel!.companyName!.toText12(isBold: true), + SizedBox( + width: 6.h, + ), + Container( + padding: EdgeInsets.symmetric(horizontal: 6.h, vertical: 3.h), + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.infoColor, + borderRadius: 50, + ), + child: insuranceViewModel.patientInsuranceUpdateResponseModel!.subCategory!.toText8(isBold: true, color: AppColors.whiteColor), + ), + ], + ), + SizedBox(height: 8.h), + Row( + children: [ + Wrap( + direction: Axis.horizontal, + spacing: 4.h, + runSpacing: 4.h, + children: [ + Row( + children: [ + CustomButton( + icon: AppAssets.doctor_calendar_icon, + iconColor: AppColors.blackColor, + iconSize: 13.h, + text: "${LocaleKeys.expiryOn.tr(context: context)} ${insuranceViewModel.patientInsuranceUpdateResponseModel!.effectiveTo}", + onPressed: () {}, + backgroundColor: AppColors.greyColor, + borderColor: AppColors.greyColor, + textColor: AppColors.blackColor, + fontSize: 10, + fontWeight: FontWeight.w500, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 30.h, + ), + ], + ), + Row( + children: [ + CustomButton( + text: "Member ID: ${insuranceViewModel.patientInsuranceUpdateResponseModel!.memberID!}", + onPressed: () {}, + backgroundColor: AppColors.greyColor, + borderColor: AppColors.greyColor, + textColor: AppColors.blackColor, + fontSize: 10, + fontWeight: FontWeight.w500, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 30.h, + ), + ], + ), + ], + ), + ], + ), + ], + ).paddingSymmetrical(16.h, 16.h), + ).paddingSymmetrical(24.h, 0.h), + SizedBox( + height: 24.h, + ), + CustomButton( + icon: AppAssets.insurance_active_icon, + iconColor: AppColors.whiteColor, + iconSize: 20.h, + text: "Update Insurance", + onPressed: () {}, + backgroundColor: AppColors.successColor, + borderColor: AppColors.successColor.withOpacity(0.01), + textColor: AppColors.whiteColor, + fontSize: 16, + fontWeight: FontWeight.w500, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 56.h, + ).paddingSymmetrical(24.h, 0.h), + SizedBox( + height: 24.h, + ), + ], + ); + } +} diff --git a/lib/presentation/insurance/widgets/patient_insurance_card.dart b/lib/presentation/insurance/widgets/patient_insurance_card.dart index 2701233..1edef84 100644 --- a/lib/presentation/insurance/widgets/patient_insurance_card.dart +++ b/lib/presentation/insurance/widgets/patient_insurance_card.dart @@ -8,8 +8,10 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart'; import 'package:hmg_patient_app_new/features/insurance/models/resp_models/patient_insurance_details_response_model.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; +import 'package:hmg_patient_app_new/presentation/insurance/widgets/insurance_update_details_card.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; +import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:provider/provider.dart'; class PatientInsuranceCard extends StatelessWidget { @@ -114,7 +116,12 @@ class PatientInsuranceCard extends StatelessWidget { iconColor: AppColors.successColor, iconSize: 15.h, text: "${LocaleKeys.updateInsurance.tr(context: context)} ${LocaleKeys.updateInsuranceSubtitle.tr(context: context)}", - onPressed: () {}, + onPressed: () { + insuranceViewModel.setIsInsuranceUpdateDetailsLoading(true); + insuranceViewModel.getPatientInsuranceDetailsForUpdate(); + showCommonBottomSheet(context, + child: PatientInsuranceCardUpdateCard(), callBackFunc: () {}, title: "", height: ResponsiveExtension.screenHeight * 0.42, isCloseButtonVisible: false, isFullScreen: false); + }, backgroundColor: AppColors.bgGreenColor.withOpacity(0.20), borderColor: AppColors.bgGreenColor.withOpacity(0.0), textColor: AppColors.bgGreenColor, diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart index 4bb5cdb..2a9f0e8 100644 --- a/lib/presentation/medical_file/medical_file_page.dart +++ b/lib/presentation/medical_file/medical_file_page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; @@ -11,15 +13,29 @@ import 'package:hmg_patient_app_new/presentation/insurance/widgets/patient_insur import 'package:hmg_patient_app_new/presentation/medical_file/widgets/medical_file_card.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; +import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart'; import 'package:hmg_patient_app_new/widgets/input_widget.dart'; import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart'; import 'package:provider/provider.dart'; -class MedicalFilePage extends StatelessWidget { +class MedicalFilePage extends StatefulWidget { MedicalFilePage({super.key}); + @override + State createState() => _MedicalFilePageState(); +} + +class _MedicalFilePageState extends State { late InsuranceViewModel insuranceViewModel; + @override + void initState() { + scheduleMicrotask(() { + insuranceViewModel.initInsuranceProvider(); + }); + super.initState(); + } + @override Widget build(BuildContext context) { insuranceViewModel = Provider.of(context); @@ -29,168 +45,178 @@ class MedicalFilePage extends StatelessWidget { title: const Text('Appointments'), backgroundColor: AppColors.bgScaffoldColor, ), - body: Padding( - padding: EdgeInsets.all(24.h), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocaleKeys.medicalFile.tr(context: context).toText22(isBold: true), - SizedBox(height: 16.h), - TextInputWidget( - labelText: LocaleKeys.search.tr(context: context), - hintText: "Type any record", - controller: TextEditingController(), - keyboardType: TextInputType.number, - isEnable: true, - prefix: null, - autoFocus: false, - isBorderAllowed: false, - isAllowLeadingIcon: true, - padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 8.h), - leadingIcon: AppAssets.student_card, + body: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.medicalFile.tr(context: context).toText22(isBold: true).paddingSymmetrical(24.h, 0.0), + SizedBox(height: 16.h), + TextInputWidget( + labelText: LocaleKeys.search.tr(context: context), + hintText: "Type any record", + controller: TextEditingController(), + keyboardType: TextInputType.number, + isEnable: true, + prefix: null, + autoFocus: false, + isBorderAllowed: false, + isAllowLeadingIcon: true, + padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 8.h), + leadingIcon: AppAssets.student_card, + ).paddingSymmetrical(24.h, 0.0), + SizedBox(height: 16.h), + Container( + width: double.infinity, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24, ), - SizedBox(height: 16.h), - Container( - width: double.infinity, - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 24, + child: Padding( + padding: EdgeInsets.all(16.h), + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image.asset( + AppAssets.male_img, + width: 56.h, + height: 56.h, + ), + SizedBox(width: 8.h), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Haroon Amjad".toText18(isBold: true), + SizedBox(height: 4.h), + Row( + children: [ + CustomButton( + icon: AppAssets.file_icon, + iconColor: AppColors.blackColor, + iconSize: 12.h, + text: "File no: 3628599", + onPressed: () {}, + backgroundColor: AppColors.greyColor, + borderColor: AppColors.greyColor, + textColor: AppColors.blackColor, + fontSize: 10, + fontWeight: FontWeight.normal, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 30.h, + ), + SizedBox(width: 4.h), + CustomButton( + text: LocaleKeys.verified.tr(context: context), + onPressed: () {}, + backgroundColor: AppColors.greyColor, + borderColor: AppColors.greyColor, + textColor: AppColors.blackColor, + fontSize: 10, + fontWeight: FontWeight.normal, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 30.h, + ), + ], + ), + ], + ) + ], + ), + SizedBox(height: 16.h), + Divider(color: AppColors.dividerColor, height: 1.h), + SizedBox(height: 16.h), + Row( + children: [ + CustomButton( + text: "30 Years Old", + onPressed: () {}, + backgroundColor: AppColors.greyColor, + borderColor: AppColors.greyColor, + textColor: AppColors.blackColor, + fontSize: 10, + fontWeight: FontWeight.normal, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 30.h, + ), + SizedBox(width: 4.h), + CustomButton( + icon: AppAssets.blood_icon, + iconColor: AppColors.primaryRedColor, + iconSize: 13.h, + text: "Blood: A+", + onPressed: () {}, + backgroundColor: AppColors.greyColor, + borderColor: AppColors.greyColor, + textColor: AppColors.blackColor, + fontSize: 10, + fontWeight: FontWeight.normal, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 30.h, + ), + SizedBox(width: 4.h), + CustomButton( + icon: AppAssets.insurance_active_icon, + iconColor: AppColors.successColor, + iconSize: 13.h, + text: "Insurance Active", + onPressed: () {}, + backgroundColor: AppColors.bgGreenColor.withOpacity(0.20), + borderColor: AppColors.bgGreenColor.withOpacity(0.0), + textColor: AppColors.blackColor, + fontSize: 10, + fontWeight: FontWeight.normal, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 30.h, + ), + ], + ), + SizedBox(height: 8.h), + ], ), - child: Padding( - padding: EdgeInsets.all(16.h), - child: Column( - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset( - AppAssets.male_img, - width: 56.h, - height: 56.h, - ), - SizedBox(width: 8.h), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - "Haroon Amjad".toText18(isBold: true), - SizedBox(height: 4.h), - Row( - children: [ - CustomButton( - icon: AppAssets.file_icon, - iconColor: AppColors.blackColor, - iconSize: 12.h, - text: "File no: 3628599", - onPressed: () {}, - backgroundColor: AppColors.greyColor, - borderColor: AppColors.greyColor, - textColor: AppColors.blackColor, - fontSize: 10, - fontWeight: FontWeight.normal, - borderRadius: 12, - padding: EdgeInsets.fromLTRB(10, 0, 10, 0), - height: 30.h, - ), - SizedBox(width: 4.h), - CustomButton( - text: LocaleKeys.verified.tr(context: context), - onPressed: () {}, - backgroundColor: AppColors.greyColor, - borderColor: AppColors.greyColor, - textColor: AppColors.blackColor, - fontSize: 10, - fontWeight: FontWeight.normal, - borderRadius: 12, - padding: EdgeInsets.fromLTRB(10, 0, 10, 0), - height: 30.h, - ), - ], - ), - ], - ) - ], - ), - SizedBox(height: 16.h), - Divider(color: AppColors.dividerColor, height: 1.h), - SizedBox(height: 16.h), - Row( - children: [ - CustomButton( - text: "30 Years Old", - onPressed: () {}, - backgroundColor: AppColors.greyColor, - borderColor: AppColors.greyColor, - textColor: AppColors.blackColor, - fontSize: 10, - fontWeight: FontWeight.normal, - borderRadius: 12, - padding: EdgeInsets.fromLTRB(10, 0, 10, 0), - height: 30.h, - ), - SizedBox(width: 4.h), - CustomButton( - icon: AppAssets.blood_icon, - iconColor: AppColors.primaryRedColor, - iconSize: 13.h, - text: "Blood: A+", - onPressed: () {}, - backgroundColor: AppColors.greyColor, - borderColor: AppColors.greyColor, - textColor: AppColors.blackColor, - fontSize: 10, - fontWeight: FontWeight.normal, - borderRadius: 12, - padding: EdgeInsets.fromLTRB(10, 0, 10, 0), - height: 30.h, - ), - SizedBox(width: 4.h), - CustomButton( - icon: AppAssets.insurance_active_icon, - iconColor: AppColors.successColor, - iconSize: 13.h, - text: "Insurance Active", - onPressed: () {}, - backgroundColor: AppColors.bgGreenColor.withOpacity(0.20), - borderColor: AppColors.bgGreenColor.withOpacity(0.0), - textColor: AppColors.blackColor, - fontSize: 10, - fontWeight: FontWeight.normal, - borderRadius: 12, - padding: EdgeInsets.fromLTRB(10, 0, 10, 0), - height: 30.h, - ), - ], - ), - SizedBox(height: 8.h), - ], - ), - ), - ), - SizedBox(height: 16.h), - //Insurance Tab Data - Consumer(builder: (context, insuranceVM, child) { - return insuranceVM.isInsuranceLoading - ? const MoviesShimmerWidget() - : PatientInsuranceCard( - insuranceCardDetailsModel: insuranceVM.patientInsuranceList.first, - isInsuranceExpired: DateTime.now().isBefore(DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo))); - }), - SizedBox(height: 10.h), - GridView( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, crossAxisSpacing: 13, mainAxisSpacing: 13), - physics: NeverScrollableScrollPhysics(), - padding: EdgeInsets.only(top: 12), - shrinkWrap: true, - children: [ - MedicalFileCard(label: "Update Insurance", textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, svgIcon: AppAssets.eye_result_icon), - MedicalFileCard(label: "Insurance Approvals", textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, svgIcon: AppAssets.eye_result_icon), - MedicalFileCard(label: "My Invoices List", textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, svgIcon: AppAssets.eye_result_icon), - MedicalFileCard(label: "Ancillary Orders List", textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, svgIcon: AppAssets.eye_result_icon), - ], ), - ], - ), + ).paddingSymmetrical(24.h, 0.0), + SizedBox(height: 16.h), + CustomTabBar( + activeTextColor: Color(0xffED1C2B), + activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1), + tabs: [ + CustomTabBarModel(AppAssets.myFilesBottom, LocaleKeys.general.tr(context: context).needTranslation), + CustomTabBarModel(AppAssets.insurance, LocaleKeys.insurance.tr(context: context)), + CustomTabBarModel(AppAssets.requests, LocaleKeys.request.tr(context: context).needTranslation), + CustomTabBarModel(AppAssets.more, "More".needTranslation), + ], + onTabChange: (index) {}, + ).paddingSymmetrical(24.h, 0.0), + SizedBox(height: 16.h), + //Insurance Tab Data + Consumer(builder: (context, insuranceVM, child) { + return insuranceVM.isInsuranceLoading + ? const MoviesShimmerWidget().paddingSymmetrical(24.h, 0.0) + : PatientInsuranceCard( + insuranceCardDetailsModel: insuranceVM.patientInsuranceList.first, + isInsuranceExpired: DateTime.now().isBefore(DateUtil.convertStringToDate(insuranceVM.patientInsuranceList.first.cardValidTo))); + }), + SizedBox(height: 10.h), + GridView( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, crossAxisSpacing: 13, mainAxisSpacing: 13), + physics: NeverScrollableScrollPhysics(), + padding: EdgeInsets.only(top: 12), + shrinkWrap: true, + children: [ + MedicalFileCard(label: "Update Insurance", textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, svgIcon: AppAssets.eye_result_icon), + MedicalFileCard(label: "Insurance Approvals", textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, svgIcon: AppAssets.eye_result_icon), + MedicalFileCard(label: "My Invoices List", textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, svgIcon: AppAssets.eye_result_icon), + MedicalFileCard(label: "Ancillary Orders List", textColor: AppColors.blackColor, backgroundColor: AppColors.whiteColor, svgIcon: AppAssets.eye_result_icon), + ], + ).paddingSymmetrical(24.h, 0.0), + SizedBox(height: 16.h), + ], ), ), ); diff --git a/lib/presentation/prescriptions/prescription_detail_page.dart b/lib/presentation/prescriptions/prescription_detail_page.dart index 65dc550..1f8e0a2 100644 --- a/lib/presentation/prescriptions/prescription_detail_page.dart +++ b/lib/presentation/prescriptions/prescription_detail_page.dart @@ -313,6 +313,7 @@ class _PrescriptionDetailPageState extends State { SizedBox(width: 12.h), Switch( activeColor: AppColors.successColor, + activeTrackColor: AppColors.successColor.withValues(alpha: .15), value: prescriptionVM.prescriptionDetailsList[index].hasReminder!, onChanged: (newValue) { setState(() { diff --git a/lib/routes/app_routes.dart b/lib/routes/app_routes.dart index d16cc62..4369157 100644 --- a/lib/routes/app_routes.dart +++ b/lib/routes/app_routes.dart @@ -4,10 +4,11 @@ import 'package:hmg_patient_app_new/splashPage.dart'; class AppRoutes { static const String initialRoute = '/initialRoute'; - static const String login = '/login'; + static const String loginScreen = '/loginScreen'; + static const String registerNewScreen = '/registerNewScreen'; static Map get routes => { initialRoute: (context) => SplashPage(), - login: (context) => LoginScreen(), + loginScreen: (context) => LoginScreen(), }; } diff --git a/lib/services/cache_service.dart b/lib/services/cache_service.dart index f25409e..8a015d8 100644 --- a/lib/services/cache_service.dart +++ b/lib/services/cache_service.dart @@ -1,14 +1,116 @@ +import 'dart:convert'; +import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:shared_preferences/shared_preferences.dart'; abstract class CacheService { + Future saveString({required String key, required String value}); + Future saveInt({required String key, required int value}); + + Future saveDouble({required String key, required double value}); + + Future saveBool({required String key, required bool value}); + + Future saveStringList({required String key, required List value}); + + String? getString({required String key}); + + int? getInt({required String key}); + + double? getDouble({required String key}); + + bool? getBool({required String key}); + + List? getStringList({required String key}); + + Future getObject({required String key}); + + Future saveObject({required String key, required dynamic value}); + + Future remove({required String key}); + + Future clear(); } class CacheServiceImp implements CacheService { - SharedPreferences sharedPreferences; + final SharedPreferences sharedPreferences; + final LoggerService loggerService; + + CacheServiceImp({ + required this.sharedPreferences, + required this.loggerService, + }); + + @override + Future saveString({required String key, required String value}) async { + await sharedPreferences.setString(key, value); + } + + @override + Future saveInt({required String key, required int value}) async { + await sharedPreferences.setInt(key, value); + } + + @override + Future saveDouble({required String key, required double value}) async { + await sharedPreferences.setDouble(key, value); + } + + @override + Future saveBool({required String key, required bool value}) async { + await sharedPreferences.setBool(key, value); + } + + @override + Future saveStringList({required String key, required List value}) async { + await sharedPreferences.setStringList(key, value); + } + + @override + String? getString({required String key}) => sharedPreferences.getString(key); + + @override + int? getInt({required String key}) => sharedPreferences.getInt(key); + + @override + double? getDouble({required String key}) => sharedPreferences.getDouble(key); + + @override + bool? getBool({required String key}) => sharedPreferences.getBool(key); + + @override + List? getStringList({required String key}) => sharedPreferences.getStringList(key); + + @override + Future remove({required String key}) async { + await sharedPreferences.remove(key); + } - CacheServiceImp({required this.sharedPreferences}); + @override + Future getObject({required String key}) async { + try { + await sharedPreferences.reload(); + var string = sharedPreferences.getString(key); + if (string == null) return null; + return json.decode(string); + } catch (ex) { + loggerService.errorLogs(ex.toString()); + return null; + } + } + @override + Future saveObject({required String key, required dynamic value}) async { + try { + await sharedPreferences.setString(key, json.encode(value)); + } catch (ex) { + loggerService.errorLogs(ex.toString()); + } + } + @override + Future clear() async { + await sharedPreferences.clear(); + } } diff --git a/lib/services/dialog_service.dart b/lib/services/dialog_service.dart index af5af9c..28b77e1 100644 --- a/lib/services/dialog_service.dart +++ b/lib/services/dialog_service.dart @@ -3,7 +3,7 @@ import 'package:hmg_patient_app_new/extensions/route_extensions.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; abstract class DialogService { - Future showErrorDialog({required String message, Function()? onOkPressed}); + Future showErrorBottomSheet({required String message, Function()? onOkPressed}); } class DialogServiceImp implements DialogService { @@ -12,7 +12,7 @@ class DialogServiceImp implements DialogService { DialogServiceImp({required this.navigationService}); @override - Future showErrorDialog({required String message, Function()? onOkPressed}) async { + Future showErrorBottomSheet({required String message, Function()? onOkPressed}) async { final context = navigationService.navigatorKey.currentContext; if (context == null) return; diff --git a/lib/services/error_handler_service.dart b/lib/services/error_handler_service.dart index a26d264..59a0205 100644 --- a/lib/services/error_handler_service.dart +++ b/lib/services/error_handler_service.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:hmg_patient_app_new/core/exceptions/api_exception.dart'; import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart'; +import 'package:hmg_patient_app_new/core/utils/loading_utils.dart'; import 'package:hmg_patient_app_new/services/dialog_service.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; @@ -45,11 +46,15 @@ class ErrorHandlerServiceImp implements ErrorHandlerService { await _showDialog(failure, title: "Unknown Error"); } else { loggerService.errorLogs("Unhandled failure type: $failure"); + await _showDialog(failure, title: "Error"); } } Future _showDialog(Failure failure, {String title = "Error", Function()? onOkPressed}) async { - await dialogService.showErrorDialog(message: failure.message, onOkPressed: onOkPressed); + if (LoadingUtils.isLoading) { + LoadingUtils.hideFullScreenLoader(); + } + await dialogService.showErrorBottomSheet(message: failure.message, onOkPressed: onOkPressed); } } diff --git a/lib/services/firebase_service.dart b/lib/services/firebase_service.dart new file mode 100644 index 0000000..f6c712e --- /dev/null +++ b/lib/services/firebase_service.dart @@ -0,0 +1,31 @@ +import 'package:firebase_messaging/firebase_messaging.dart' show FirebaseMessaging; +import 'package:hmg_patient_app_new/core/app_state.dart'; +import 'package:hmg_patient_app_new/services/logger_service.dart'; + +abstract class FirebaseService { + Future getDeviceToken(); +} + +class FirebaseServiceImpl implements FirebaseService { + final FirebaseMessaging firebaseMessaging; + final LoggerService loggerService; + final AppState appState; + + FirebaseServiceImpl({ + required this.firebaseMessaging, + required this.loggerService, + required this.appState, + }); + + @override + Future getDeviceToken() async { + try { + String? deviceToken = await firebaseMessaging.getToken(); + appState.setDeviceToken = deviceToken; + return deviceToken ?? ""; + } catch (e) { + loggerService.logInfo(e.toString()); + return ""; + } + } +} diff --git a/lib/services/logger_service.dart b/lib/services/logger_service.dart index 0b33c52..9df6633 100644 --- a/lib/services/logger_service.dart +++ b/lib/services/logger_service.dart @@ -1,8 +1,6 @@ - import 'package:logger/logger.dart'; abstract class LoggerService { - void errorLogs(String message); void logInfo(String message); @@ -13,8 +11,6 @@ class LoggerServiceImp implements LoggerService { LoggerServiceImp({required this.logger}); - - @override void errorLogs(String message) { logger.e(message); @@ -22,6 +18,6 @@ class LoggerServiceImp implements LoggerService { @override void logInfo(String message) { - logger.i(message); + logger.d(message); } } diff --git a/lib/services/navigation_service.dart b/lib/services/navigation_service.dart index d814cf5..6dd4a54 100644 --- a/lib/services/navigation_service.dart +++ b/lib/services/navigation_service.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:hmg_patient_app_new/features/authentication/widgets/otp_verification_screen.dart'; class NavigationService { final GlobalKey navigatorKey = GlobalKey(); @@ -12,4 +13,38 @@ class NavigationService { void pop([T? result]) { navigatorKey.currentState!.pop(result); } + + void popUntilNamed(String routeName) { + navigatorKey.currentState?.popUntil(ModalRoute.withName(routeName)); + } + + Future pushToOtpScreen({ + required String phoneNumber, + required Function(int code) checkActivationCode, + required Function(String phoneNumber) onResendOTPPressed, + }) { + return navigatorKey.currentState!.push( + MaterialPageRoute( + builder: (_) => OTPVerificationScreen( + phoneNumber: phoneNumber, + checkActivationCode: checkActivationCode, + onResendOTPPressed: onResendOTPPressed, + ), + ), + ); + } + + Future pushPage({ + required Widget page, + bool fullscreenDialog = false, + bool maintainState = true, + }) { + return navigatorKey.currentState!.push( + MaterialPageRoute( + builder: (_) => page, + fullscreenDialog: fullscreenDialog, + maintainState: maintainState, + ), + ); + } } diff --git a/lib/services/permission_service.dart b/lib/services/permission_service.dart new file mode 100644 index 0000000..6287234 --- /dev/null +++ b/lib/services/permission_service.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; + +import 'package:permission_handler/permission_handler.dart'; + +// import 'package:vibration/vibration.dart'; +import 'package:geolocator/geolocator.dart' as geo; + +class PermissionService { + // final LocalStorage storage = new LocalStorage("permission"); + geo.LocationPermission? locationPermission; + + // AppGlobal appGlobal = new AppGlobal(); + + // setVibrationPermission(flag) async { + // storage.setItem('isVibration', flag); + // } + // + // isVibrationEnabled() { + // return (storage.getItem('isVibration') == null) || + // (storage.getItem('isVibration')) == false + // ? false + // : true; + // } + + // vibrate(callback, context) async { + // if (callback == null) return null; + // if (isVibrationEnabled() == true) { + // // if (await Vibration.hasVibrator() !=null) { + // // Vibration.vibrate(duration: 100); + // // callback(); + // // } + // } else { + // callback(); + // } + // } + + // setTheme(flag) async { + // storage.setItem('isTheme', flag); + // } + // + // isThemeEnabled() { + // return storage.getItem('isTheme'); + // } + + cameraPermission() async { + Map statuses = await [ + Permission.camera, + ].request(); + } + + static isCameraEnabled() async { + return await Permission.camera.isGranted; + } + + static isExternalStorageEnabled() async { + return await Permission.storage.isGranted; + } + + static isHealthDataPermissionEnabled() async { + return await Permission.sensors.isGranted; + } + + static isMicrophonePermissionEnabled() async { + return await Permission.microphone.isGranted; + } + + static isCalendarPermissionEnabled() async { + return await Permission.calendarFullAccess.isGranted; + } + + setCameraLocationPermission(context) async { + Navigator.pop(context); + openAppSettings(); + } + + static isLocationEnabled() async { + var permission = await geo.Geolocator.checkPermission(); + if (permission == geo.LocationPermission.denied) { + return false; + } else { + return true; + } + } + + openSettings() async { + openAppSettings(); + } + + openAccessbility() { + // OpenSettings.openAppSetting(); + } +} diff --git a/lib/splashPage.dart b/lib/splashPage.dart index 6136d22..b852cd4 100644 --- a/lib/splashPage.dart +++ b/lib/splashPage.dart @@ -16,7 +16,7 @@ import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/transitions/fade_page.dart'; import 'package:provider/provider.dart'; -import 'core/consts.dart'; +import 'core/cache_consts.dart'; import 'core/utils/local_notifications.dart'; import 'core/utils/push_notification_handler.dart'; diff --git a/lib/widgets/bottomsheet/generic_bottom_sheet.dart b/lib/widgets/bottomsheet/generic_bottom_sheet.dart index 08bf849..74062ef 100644 --- a/lib/widgets/bottomsheet/generic_bottom_sheet.dart +++ b/lib/widgets/bottomsheet/generic_bottom_sheet.dart @@ -1,4 +1,5 @@ import 'dart:io'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; @@ -25,6 +26,7 @@ class GenericBottomSheet extends StatefulWidget { // FocusNode myFocusNode; GenericBottomSheet({ + super.key, this.countryCode = "", this.initialPhoneNumber = "", required this.buttons, @@ -47,7 +49,7 @@ class _GenericBottomSheetState extends State { super.initState(); if (!widget.isForEmail && widget.textController != null) { - widget.textController!.text = widget.initialPhoneNumber!; + widget.textController!.text = widget.initialPhoneNumber ?? ""; } } diff --git a/lib/widgets/custom_tab_bar.dart b/lib/widgets/custom_tab_bar.dart new file mode 100644 index 0000000..b6c8ef3 --- /dev/null +++ b/lib/widgets/custom_tab_bar.dart @@ -0,0 +1,113 @@ +import 'package:flutter/material.dart'; +import 'package:hmg_patient_app_new/core/app_assets.dart'; +import 'package:hmg_patient_app_new/core/app_export.dart'; +import 'package:hmg_patient_app_new/core/utils/utils.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/extensions/widget_extensions.dart'; + +class CustomTabBarModel { + String? image; + String title; + + CustomTabBarModel(this.image, this.title); +} + +class CustomTabBar extends StatefulWidget { + final int initialIndex = 0; + final List tabs; + final Color activeTextColor; + final Color activeBackgroundColor; + final Color inActiveTextColor; + final Color inActiveBackgroundColor; + final Function(int)? onTabChange; + + CustomTabBar( + {Key? key, + required this.tabs, + this.activeTextColor = const Color(0xff2E3039), + this.inActiveTextColor = const Color(0xff898A8D), + this.activeBackgroundColor = const Color(0x142E3039), + this.inActiveBackgroundColor = Colors.white, + this.onTabChange}) + : super(key: key); + + @override + _CustomTabBarState createState() { + return _CustomTabBarState(); + } +} + +class _CustomTabBarState extends State { + int selectedIndex = 0; + + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + super.dispose(); + } + + void callBackCurrentIndex() { + if (widget.onTabChange != null) widget.onTabChange!(selectedIndex); + } + + @override + Widget build(BuildContext context) { + late Widget parentWidget; + + if (widget.tabs.length > 3) { + parentWidget = ListView.separated( + scrollDirection: Axis.horizontal, + padding: EdgeInsets.zero, + physics: const BouncingScrollPhysics(), + itemBuilder: (cxt, index) => myTab(widget.tabs[index], index), + separatorBuilder: (cxt, index) => 4.width, + itemCount: widget.tabs.length, + ); + } else { + parentWidget = Row( + spacing: 4, + children: [for (int i = 0; i < widget.tabs.length; i++) myTab(widget.tabs[i], i).expanded], + ); + } + + return Container( + height: 62.h, + padding: EdgeInsets.all(4), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(11), + ), + child: parentWidget); + } + + Widget myTab(CustomTabBarModel tabBar, int currentIndex) { + bool isSelected = selectedIndex == currentIndex; + return Container( + height: 54.h, + padding: EdgeInsets.only(top: 4, bottom: 4, left: 16, right: 16), + alignment: Alignment.center, + decoration: BoxDecoration( + color: isSelected ? widget.activeBackgroundColor : widget.inActiveBackgroundColor, + borderRadius: BorderRadius.circular(7), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + spacing: 4, + children: [ + if (tabBar.image != null) Utils.buildSvgWithAssets(icon: tabBar.image!, height: 18, width: 18, iconColor: isSelected ? widget.activeTextColor : widget.inActiveTextColor), + tabBar.title + .toText16(weight: isSelected ? FontWeight.w600 : FontWeight.w500, color: isSelected ? widget.activeTextColor : widget.inActiveTextColor, letterSpacing: isSelected ? -0.3 : -0.1), + ], + )).onPress(() { + setState(() { + selectedIndex = currentIndex; + }); + callBackCurrentIndex(); + }); + } +} diff --git a/lib/widgets/input_widget.dart b/lib/widgets/input_widget.dart index 0f520c6..53a0130 100644 --- a/lib/widgets/input_widget.dart +++ b/lib/widgets/input_widget.dart @@ -34,13 +34,13 @@ class TextInputWidget extends StatelessWidget { final bool hasError; final String? errorMessage; Function(CountryEnum)? onCountryChange; - SelectionTypeEnum? selectionType; + final SelectionTypeEnum? selectionType; // final List countryList; // final Function(Country)? onCountryChange; TextInputWidget({ - Key? key, + super.key, required this.labelText, required this.hintText, this.controller, @@ -63,7 +63,7 @@ class TextInputWidget extends StatelessWidget { this.selectionType, // this.countryList = const [], // this.onCountryChange, - }) : super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/pubspec.lock b/pubspec.lock deleted file mode 100644 index c503e1b..0000000 --- a/pubspec.lock +++ /dev/null @@ -1,1640 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _flutterfire_internals: - dependency: transitive - description: - name: _flutterfire_internals - sha256: ff0a84a2734d9e1089f8aedd5c0af0061b82fb94e95260d943404e0ef2134b11 - url: "https://pub.dev" - source: hosted - version: "1.3.59" - archive: - dependency: transitive - description: - name: archive - sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" - url: "https://pub.dev" - source: hosted - version: "4.0.7" - args: - dependency: transitive - description: - name: args - sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.dev" - source: hosted - version: "2.7.0" - async: - dependency: transitive - description: - name: async - sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 - url: "https://pub.dev" - source: hosted - version: "2.12.0" - audio_session: - dependency: transitive - description: - name: audio_session - sha256: "2b7fff16a552486d078bfc09a8cde19f426dc6d6329262b684182597bec5b1ac" - url: "https://pub.dev" - source: hosted - version: "0.1.25" - auto_size_text: - dependency: "direct main" - description: - name: auto_size_text - sha256: "3f5261cd3fb5f2a9ab4e2fc3fba84fd9fcaac8821f20a1d4e71f557521b22599" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - cached_network_image: - dependency: "direct main" - description: - name: cached_network_image - sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916" - url: "https://pub.dev" - source: hosted - version: "3.4.1" - cached_network_image_platform_interface: - dependency: transitive - description: - name: cached_network_image_platform_interface - sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829" - url: "https://pub.dev" - source: hosted - version: "4.1.1" - cached_network_image_web: - dependency: transitive - description: - name: cached_network_image_web - sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062" - url: "https://pub.dev" - source: hosted - version: "1.3.1" - carp_serializable: - dependency: transitive - description: - name: carp_serializable - sha256: f039f8ea22e9437aef13fe7e9743c3761c76d401288dcb702eadd273c3e4dcef - url: "https://pub.dev" - source: hosted - version: "2.0.1" - characters: - dependency: transitive - description: - name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - clock: - dependency: transitive - description: - name: clock - sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.dev" - source: hosted - version: "1.1.2" - collection: - dependency: transitive - description: - name: collection - sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" - source: hosted - version: "1.19.1" - connectivity_plus: - dependency: "direct main" - description: - name: connectivity_plus - sha256: b5e72753cf63becce2c61fd04dfe0f1c430cc5278b53a1342dc5ad839eab29ec - url: "https://pub.dev" - source: hosted - version: "6.1.5" - connectivity_plus_platform_interface: - dependency: transitive - description: - name: connectivity_plus_platform_interface - sha256: "42657c1715d48b167930d5f34d00222ac100475f73d10162ddf43e714932f204" - url: "https://pub.dev" - source: hosted - version: "2.0.1" - cross_file: - dependency: transitive - description: - name: cross_file - sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" - url: "https://pub.dev" - source: hosted - version: "0.3.4+2" - crypto: - dependency: transitive - description: - name: crypto - sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" - url: "https://pub.dev" - source: hosted - version: "3.0.6" - csslib: - dependency: transitive - description: - name: csslib - sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" - url: "https://pub.dev" - source: hosted - version: "1.0.2" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.dev" - source: hosted - version: "1.0.8" - dartz: - dependency: "direct main" - description: - name: dartz - sha256: e6acf34ad2e31b1eb00948692468c30ab48ac8250e0f0df661e29f12dd252168 - url: "https://pub.dev" - source: hosted - version: "0.10.1" - dbus: - dependency: transitive - description: - name: dbus - sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" - url: "https://pub.dev" - source: hosted - version: "0.7.11" - device_calendar: - dependency: "direct main" - description: - path: "." - ref: HEAD - resolved-ref: "5ea5ed9e2bb499c0633383b53103f2920b634755" - url: "https://github.com/bardram/device_calendar" - source: git - version: "4.3.1" - device_info_plus: - dependency: "direct main" - description: - name: device_info_plus - sha256: "98f28b42168cc509abc92f88518882fd58061ea372d7999aecc424345c7bff6a" - url: "https://pub.dev" - source: hosted - version: "11.5.0" - device_info_plus_platform_interface: - dependency: transitive - description: - name: device_info_plus_platform_interface - sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f - url: "https://pub.dev" - source: hosted - version: "7.0.3" - dropdown_search: - dependency: "direct main" - description: - name: dropdown_search - sha256: c29b3e5147a82a06a4a08b3b574c51cb48cc17ad89893d53ee72a6f86643622e - url: "https://pub.dev" - source: hosted - version: "6.0.2" - easy_localization: - dependency: "direct main" - description: - name: easy_localization - sha256: "2ccdf9db8fe4d9c5a75c122e6275674508fd0f0d49c827354967b8afcc56bbed" - url: "https://pub.dev" - source: hosted - version: "3.0.8" - easy_logger: - dependency: transitive - description: - name: easy_logger - sha256: c764a6e024846f33405a2342caf91c62e357c24b02c04dbc712ef232bf30ffb7 - url: "https://pub.dev" - source: hosted - version: "0.0.2" - equatable: - dependency: "direct main" - description: - name: equatable - sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7" - url: "https://pub.dev" - source: hosted - version: "2.0.7" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.dev" - source: hosted - version: "1.3.3" - ffi: - dependency: transitive - description: - name: ffi - sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - file: - dependency: transitive - description: - name: file - sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.dev" - source: hosted - version: "7.0.1" - file_picker: - dependency: "direct main" - description: - name: file_picker - sha256: e7e16c9d15c36330b94ca0e2ad8cb61f93cd5282d0158c09805aed13b5452f22 - url: "https://pub.dev" - source: hosted - version: "10.3.2" - file_selector_linux: - dependency: transitive - description: - name: file_selector_linux - sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33" - url: "https://pub.dev" - source: hosted - version: "0.9.3+2" - file_selector_macos: - dependency: transitive - description: - name: file_selector_macos - sha256: "19124ff4a3d8864fdc62072b6a2ef6c222d55a3404fe14893a3c02744907b60c" - url: "https://pub.dev" - source: hosted - version: "0.9.4+4" - file_selector_platform_interface: - dependency: transitive - description: - name: file_selector_platform_interface - sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b - url: "https://pub.dev" - source: hosted - version: "2.6.2" - file_selector_windows: - dependency: transitive - description: - name: file_selector_windows - sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b" - url: "https://pub.dev" - source: hosted - version: "0.9.3+4" - firebase_analytics: - dependency: "direct main" - description: - name: firebase_analytics - sha256: "4f85b161772e1d54a66893ef131c0a44bd9e552efa78b33d5f4f60d2caa5c8a3" - url: "https://pub.dev" - source: hosted - version: "11.6.0" - firebase_analytics_platform_interface: - dependency: transitive - description: - name: firebase_analytics_platform_interface - sha256: a44b6d1155ed5cae7641e3de7163111cfd9f6f6c954ca916dc6a3bdfa86bf845 - url: "https://pub.dev" - source: hosted - version: "4.4.3" - firebase_analytics_web: - dependency: transitive - description: - name: firebase_analytics_web - sha256: c7d1ed1f86ae64215757518af5576ff88341c8ce5741988c05cc3b2e07b0b273 - url: "https://pub.dev" - source: hosted - version: "0.5.10+16" - firebase_core: - dependency: "direct main" - description: - name: firebase_core - sha256: "7be63a3f841fc9663342f7f3a011a42aef6a61066943c90b1c434d79d5c995c5" - url: "https://pub.dev" - source: hosted - version: "3.15.2" - firebase_core_platform_interface: - dependency: transitive - description: - name: firebase_core_platform_interface - sha256: "5dbc900677dcbe5873d22ad7fbd64b047750124f1f9b7ebe2a33b9ddccc838eb" - url: "https://pub.dev" - source: hosted - version: "6.0.0" - firebase_core_web: - dependency: transitive - description: - name: firebase_core_web - sha256: "0ed0dc292e8f9ac50992e2394e9d336a0275b6ae400d64163fdf0a8a8b556c37" - url: "https://pub.dev" - source: hosted - version: "2.24.1" - firebase_messaging: - dependency: "direct main" - description: - name: firebase_messaging - sha256: "60be38574f8b5658e2f22b7e311ff2064bea835c248424a383783464e8e02fcc" - url: "https://pub.dev" - source: hosted - version: "15.2.10" - firebase_messaging_platform_interface: - dependency: transitive - description: - name: firebase_messaging_platform_interface - sha256: "685e1771b3d1f9c8502771ccc9f91485b376ffe16d553533f335b9183ea99754" - url: "https://pub.dev" - source: hosted - version: "4.6.10" - firebase_messaging_web: - dependency: transitive - description: - name: firebase_messaging_web - sha256: "0d1be17bc89ed3ff5001789c92df678b2e963a51b6fa2bdb467532cc9dbed390" - url: "https://pub.dev" - source: hosted - version: "3.10.10" - fixnum: - dependency: transitive - description: - name: fixnum - sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be - url: "https://pub.dev" - source: hosted - version: "1.1.1" - fl_chart: - dependency: "direct main" - description: - name: fl_chart - sha256: "577aeac8ca414c25333334d7c4bb246775234c0e44b38b10a82b559dd4d764e7" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_cache_manager: - dependency: transitive - description: - name: flutter_cache_manager - sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386" - url: "https://pub.dev" - source: hosted - version: "3.4.1" - flutter_hooks: - dependency: transitive - description: - name: flutter_hooks - sha256: cde36b12f7188c85286fba9b38cc5a902e7279f36dd676967106c041dc9dde70 - url: "https://pub.dev" - source: hosted - version: "0.20.5" - flutter_inappwebview: - dependency: "direct main" - description: - name: flutter_inappwebview - sha256: "80092d13d3e29b6227e25b67973c67c7210bd5e35c4b747ca908e31eb71a46d5" - url: "https://pub.dev" - source: hosted - version: "6.1.5" - flutter_inappwebview_android: - dependency: transitive - description: - name: flutter_inappwebview_android - sha256: "62557c15a5c2db5d195cb3892aab74fcaec266d7b86d59a6f0027abd672cddba" - url: "https://pub.dev" - source: hosted - version: "1.1.3" - flutter_inappwebview_internal_annotations: - dependency: transitive - description: - name: flutter_inappwebview_internal_annotations - sha256: "787171d43f8af67864740b6f04166c13190aa74a1468a1f1f1e9ee5b90c359cd" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - flutter_inappwebview_ios: - dependency: transitive - description: - name: flutter_inappwebview_ios - sha256: "5818cf9b26cf0cbb0f62ff50772217d41ea8d3d9cc00279c45f8aabaa1b4025d" - url: "https://pub.dev" - source: hosted - version: "1.1.2" - flutter_inappwebview_macos: - dependency: transitive - description: - name: flutter_inappwebview_macos - sha256: c1fbb86af1a3738e3541364d7d1866315ffb0468a1a77e34198c9be571287da1 - url: "https://pub.dev" - source: hosted - version: "1.1.2" - flutter_inappwebview_platform_interface: - dependency: transitive - description: - name: flutter_inappwebview_platform_interface - sha256: cf5323e194096b6ede7a1ca808c3e0a078e4b33cc3f6338977d75b4024ba2500 - url: "https://pub.dev" - source: hosted - version: "1.3.0+1" - flutter_inappwebview_web: - dependency: transitive - description: - name: flutter_inappwebview_web - sha256: "55f89c83b0a0d3b7893306b3bb545ba4770a4df018204917148ebb42dc14a598" - url: "https://pub.dev" - source: hosted - version: "1.1.2" - flutter_inappwebview_windows: - dependency: transitive - description: - name: flutter_inappwebview_windows - sha256: "8b4d3a46078a2cdc636c4a3d10d10f2a16882f6be607962dbfff8874d1642055" - url: "https://pub.dev" - source: hosted - version: "0.6.0" - flutter_ios_voip_kit_karmm: - dependency: "direct main" - description: - name: flutter_ios_voip_kit_karmm - sha256: "31a445d78aacacdf128a0354efb9f4e424285dfe4c0af3ea872e64f03e6f6bfc" - url: "https://pub.dev" - source: hosted - version: "0.8.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" - url: "https://pub.dev" - source: hosted - version: "5.0.0" - flutter_local_notifications: - dependency: "direct main" - description: - name: flutter_local_notifications - sha256: a9966c850de5e445331b854fa42df96a8020066d67f125a5964cbc6556643f68 - url: "https://pub.dev" - source: hosted - version: "19.4.1" - flutter_local_notifications_linux: - dependency: transitive - description: - name: flutter_local_notifications_linux - sha256: e3c277b2daab8e36ac5a6820536668d07e83851aeeb79c446e525a70710770a5 - url: "https://pub.dev" - source: hosted - version: "6.0.0" - flutter_local_notifications_platform_interface: - dependency: transitive - description: - name: flutter_local_notifications_platform_interface - sha256: "277d25d960c15674ce78ca97f57d0bae2ee401c844b6ac80fcd972a9c99d09fe" - url: "https://pub.dev" - source: hosted - version: "9.1.0" - flutter_local_notifications_windows: - dependency: transitive - description: - name: flutter_local_notifications_windows - sha256: ed46d7ae4ec9d19e4c8fa2badac5fe27ba87a3fe387343ce726f927af074ec98 - url: "https://pub.dev" - source: hosted - version: "1.0.2" - flutter_localizations: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_plugin_android_lifecycle: - dependency: transitive - description: - name: flutter_plugin_android_lifecycle - sha256: b0694b7fb1689b0e6cc193b3f1fcac6423c4f93c74fb20b806c6b6f196db0c31 - url: "https://pub.dev" - source: hosted - version: "2.0.30" - flutter_rating_bar: - dependency: "direct main" - description: - name: flutter_rating_bar - sha256: d2af03469eac832c591a1eba47c91ecc871fe5708e69967073c043b2d775ed93 - url: "https://pub.dev" - source: hosted - version: "4.0.1" - flutter_staggered_animations: - dependency: "direct main" - description: - name: flutter_staggered_animations - sha256: "81d3c816c9bb0dca9e8a5d5454610e21ffb068aedb2bde49d2f8d04f75538351" - url: "https://pub.dev" - source: hosted - version: "1.1.1" - flutter_svg: - dependency: "direct main" - description: - name: flutter_svg - sha256: cd57f7969b4679317c17af6fd16ee233c1e60a82ed209d8a475c54fd6fd6f845 - url: "https://pub.dev" - source: hosted - version: "2.2.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - flutter_zoom_videosdk: - dependency: "direct main" - description: - name: flutter_zoom_videosdk - sha256: "46a4dea664b1c969099328a499c198a1755adf9ac333dea28bea5187910b3bf9" - url: "https://pub.dev" - source: hosted - version: "2.1.10" - fluttertoast: - dependency: "direct main" - description: - name: fluttertoast - sha256: "25e51620424d92d3db3832464774a6143b5053f15e382d8ffbfd40b6e795dcf1" - url: "https://pub.dev" - source: hosted - version: "8.2.12" - geoclue: - dependency: transitive - description: - name: geoclue - sha256: c2a998c77474fc57aa00c6baa2928e58f4b267649057a1c76738656e9dbd2a7f - url: "https://pub.dev" - source: hosted - version: "0.1.1" - geolocator: - dependency: "direct main" - description: - name: geolocator - sha256: "79939537046c9025be47ec645f35c8090ecadb6fe98eba146a0d25e8c1357516" - url: "https://pub.dev" - source: hosted - version: "14.0.2" - geolocator_android: - dependency: transitive - description: - name: geolocator_android - sha256: "179c3cb66dfa674fc9ccbf2be872a02658724d1c067634e2c427cf6df7df901a" - url: "https://pub.dev" - source: hosted - version: "5.0.2" - geolocator_apple: - dependency: transitive - description: - name: geolocator_apple - sha256: dbdd8789d5aaf14cf69f74d4925ad1336b4433a6efdf2fce91e8955dc921bf22 - url: "https://pub.dev" - source: hosted - version: "2.3.13" - geolocator_linux: - dependency: transitive - description: - name: geolocator_linux - sha256: c4e966f0a7a87e70049eac7a2617f9e16fd4c585a26e4330bdfc3a71e6a721f3 - url: "https://pub.dev" - source: hosted - version: "0.2.3" - geolocator_platform_interface: - dependency: transitive - description: - name: geolocator_platform_interface - sha256: "30cb64f0b9adcc0fb36f628b4ebf4f731a2961a0ebd849f4b56200205056fe67" - url: "https://pub.dev" - source: hosted - version: "4.2.6" - geolocator_web: - dependency: transitive - description: - name: geolocator_web - sha256: b1ae9bdfd90f861fde8fd4f209c37b953d65e92823cb73c7dee1fa021b06f172 - url: "https://pub.dev" - source: hosted - version: "4.1.3" - geolocator_windows: - dependency: transitive - description: - name: geolocator_windows - sha256: "175435404d20278ffd220de83c2ca293b73db95eafbdc8131fe8609be1421eb6" - url: "https://pub.dev" - source: hosted - version: "0.2.5" - get_it: - dependency: "direct main" - description: - name: get_it - sha256: a4292e7cf67193f8e7c1258203104eb2a51ec8b3a04baa14695f4064c144297b - url: "https://pub.dev" - source: hosted - version: "8.2.0" - google_api_availability: - dependency: "direct main" - description: - name: google_api_availability - sha256: "2ffdc91e1e0cf4e7974fef6c2988a24cefa81f03526ff04b694df6dc0fcbca03" - url: "https://pub.dev" - source: hosted - version: "5.0.1" - google_api_availability_android: - dependency: transitive - description: - name: google_api_availability_android - sha256: "4794147f43a8f3eee6b514d3ae30dbe6f7b9048cae8cd2a74cb4055cd28d74a8" - url: "https://pub.dev" - source: hosted - version: "1.1.1" - google_api_availability_platform_interface: - dependency: transitive - description: - name: google_api_availability_platform_interface - sha256: "65b7da62fe5b582bb3d508628ad827d36d890710ea274766a992a56fa5420da6" - url: "https://pub.dev" - source: hosted - version: "1.0.1" - google_maps: - dependency: transitive - description: - name: google_maps - sha256: "4d6e199c561ca06792c964fa24b2bac7197bf4b401c2e1d23e345e5f9939f531" - url: "https://pub.dev" - source: hosted - version: "8.1.1" - google_maps_flutter: - dependency: "direct main" - description: - name: google_maps_flutter - sha256: e1805e5a5885bd14a1c407c59229f478af169bf4d04388586b19f53145a5db3a - url: "https://pub.dev" - source: hosted - version: "2.12.3" - google_maps_flutter_android: - dependency: transitive - description: - name: google_maps_flutter_android - sha256: a6c9d43f6a944ff4bae5c3deb34817970ac3d591dcd7f5bd2ea450ab9e9c514a - url: "https://pub.dev" - source: hosted - version: "2.18.2" - google_maps_flutter_ios: - dependency: transitive - description: - name: google_maps_flutter_ios - sha256: ca02463b19a9abc7d31fcaf22631d021d647107467f741b917a69fa26659fd75 - url: "https://pub.dev" - source: hosted - version: "2.15.5" - google_maps_flutter_platform_interface: - dependency: transitive - description: - name: google_maps_flutter_platform_interface - sha256: f4b9b44f7b12a1f6707ffc79d082738e0b7e194bf728ee61d2b3cdf5fdf16081 - url: "https://pub.dev" - source: hosted - version: "2.14.0" - google_maps_flutter_web: - dependency: transitive - description: - name: google_maps_flutter_web - sha256: "9d57993ba29b80bb637bb7b9784159ca93071d5940e4d0383ae2358ad371e375" - url: "https://pub.dev" - source: hosted - version: "0.5.13" - gsettings: - dependency: transitive - description: - name: gsettings - sha256: "1b0ce661f5436d2db1e51f3c4295a49849f03d304003a7ba177d01e3a858249c" - url: "https://pub.dev" - source: hosted - version: "0.2.8" - health: - dependency: "direct main" - description: - name: health - sha256: "996664904194b8e0a09dfe761e168fdbf9ef43c51e7de39cd075de71c7258ada" - url: "https://pub.dev" - source: hosted - version: "13.1.3" - html: - dependency: transitive - description: - name: html - sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" - url: "https://pub.dev" - source: hosted - version: "0.15.6" - http: - dependency: "direct main" - description: - name: http - sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007 - url: "https://pub.dev" - source: hosted - version: "1.5.0" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.dev" - source: hosted - version: "4.1.2" - image_picker: - dependency: "direct main" - description: - name: image_picker - sha256: "736eb56a911cf24d1859315ad09ddec0b66104bc41a7f8c5b96b4e2620cf5041" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - image_picker_android: - dependency: transitive - description: - name: image_picker_android - sha256: "28f3987ca0ec702d346eae1d90eda59603a2101b52f1e234ded62cff1d5cfa6e" - url: "https://pub.dev" - source: hosted - version: "0.8.13+1" - image_picker_for_web: - dependency: transitive - description: - name: image_picker_for_web - sha256: "40c2a6a0da15556dc0f8e38a3246064a971a9f512386c3339b89f76db87269b6" - url: "https://pub.dev" - source: hosted - version: "3.1.0" - image_picker_ios: - dependency: transitive - description: - name: image_picker_ios - sha256: eb06fe30bab4c4497bad449b66448f50edcc695f1c59408e78aa3a8059eb8f0e - url: "https://pub.dev" - source: hosted - version: "0.8.13" - image_picker_linux: - dependency: transitive - description: - name: image_picker_linux - sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4" - url: "https://pub.dev" - source: hosted - version: "0.2.2" - image_picker_macos: - dependency: transitive - description: - name: image_picker_macos - sha256: d58cd9d67793d52beefd6585b12050af0a7663c0c2a6ece0fb110a35d6955e04 - url: "https://pub.dev" - source: hosted - version: "0.2.2" - image_picker_platform_interface: - dependency: transitive - description: - name: image_picker_platform_interface - sha256: "9f143b0dba3e459553209e20cc425c9801af48e6dfa4f01a0fcf927be3f41665" - url: "https://pub.dev" - source: hosted - version: "2.11.0" - image_picker_windows: - dependency: transitive - description: - name: image_picker_windows - sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae - url: "https://pub.dev" - source: hosted - version: "0.2.2" - intl: - dependency: transitive - description: - name: intl - sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" - url: "https://pub.dev" - source: hosted - version: "0.20.2" - json_annotation: - dependency: transitive - description: - name: json_annotation - sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" - url: "https://pub.dev" - source: hosted - version: "4.9.0" - just_audio: - dependency: "direct main" - description: - name: just_audio - sha256: "679637a3ec5b6e00f36472f5a3663667df00ee4822cbf5dafca0f568c710960a" - url: "https://pub.dev" - source: hosted - version: "0.10.4" - just_audio_platform_interface: - dependency: transitive - description: - name: just_audio_platform_interface - sha256: "2532c8d6702528824445921c5ff10548b518b13f808c2e34c2fd54793b999a6a" - url: "https://pub.dev" - source: hosted - version: "4.6.0" - just_audio_web: - dependency: transitive - description: - name: just_audio_web - sha256: "6ba8a2a7e87d57d32f0f7b42856ade3d6a9fbe0f1a11fabae0a4f00bb73f0663" - url: "https://pub.dev" - source: hosted - version: "0.4.16" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0" - url: "https://pub.dev" - source: hosted - version: "11.0.1" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" - url: "https://pub.dev" - source: hosted - version: "3.0.10" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - lints: - dependency: transitive - description: - name: lints - sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 - url: "https://pub.dev" - source: hosted - version: "5.1.1" - local_auth: - dependency: "direct main" - description: - name: local_auth - sha256: "434d854cf478f17f12ab29a76a02b3067f86a63a6d6c4eb8fbfdcfe4879c1b7b" - url: "https://pub.dev" - source: hosted - version: "2.3.0" - local_auth_android: - dependency: transitive - description: - name: local_auth_android - sha256: "48924f4a8b3cc45994ad5993e2e232d3b00788a305c1bf1c7db32cef281ce9a3" - url: "https://pub.dev" - source: hosted - version: "1.0.52" - local_auth_darwin: - dependency: transitive - description: - name: local_auth_darwin - sha256: "0e9706a8543a4a2eee60346294d6a633dd7c3ee60fae6b752570457c4ff32055" - url: "https://pub.dev" - source: hosted - version: "1.6.0" - local_auth_platform_interface: - dependency: transitive - description: - name: local_auth_platform_interface - sha256: "1b842ff177a7068442eae093b64abe3592f816afd2a533c0ebcdbe40f9d2075a" - url: "https://pub.dev" - source: hosted - version: "1.0.10" - local_auth_windows: - dependency: transitive - description: - name: local_auth_windows - sha256: bc4e66a29b0fdf751aafbec923b5bed7ad6ed3614875d8151afe2578520b2ab5 - url: "https://pub.dev" - source: hosted - version: "1.0.11" - logger: - dependency: "direct main" - description: - name: logger - sha256: "55d6c23a6c15db14920e037fe7e0dc32e7cdaf3b64b4b25df2d541b5b6b81c0c" - url: "https://pub.dev" - source: hosted - version: "2.6.1" - lottie: - dependency: "direct main" - description: - name: lottie - sha256: c5fa04a80a620066c15cf19cc44773e19e9b38e989ff23ea32e5903ef1015950 - url: "https://pub.dev" - source: hosted - version: "3.3.1" - manage_calendar_events: - dependency: "direct main" - description: - name: manage_calendar_events - sha256: f17600fcb7dc7047120c185993045e493d686930237b4e3c2689c26a64513d66 - url: "https://pub.dev" - source: hosted - version: "2.0.3" - matcher: - dependency: transitive - description: - name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 - url: "https://pub.dev" - source: hosted - version: "0.12.17" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.dev" - source: hosted - version: "0.11.1" - meta: - dependency: transitive - description: - name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c - url: "https://pub.dev" - source: hosted - version: "1.16.0" - mime: - dependency: transitive - description: - name: mime - sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - nested: - dependency: transitive - description: - name: nested - sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - nm: - dependency: transitive - description: - name: nm - sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254" - url: "https://pub.dev" - source: hosted - version: "0.5.0" - octo_image: - dependency: transitive - description: - name: octo_image - sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - package_info_plus: - dependency: transitive - description: - name: package_info_plus - sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968" - url: "https://pub.dev" - source: hosted - version: "8.3.1" - package_info_plus_platform_interface: - dependency: transitive - description: - name: package_info_plus_platform_interface - sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" - url: "https://pub.dev" - source: hosted - version: "3.2.1" - path: - dependency: transitive - description: - name: path - sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" - source: hosted - version: "1.9.1" - path_parsing: - dependency: transitive - description: - name: path_parsing - sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - path_provider: - dependency: transitive - description: - name: path_provider - sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" - url: "https://pub.dev" - source: hosted - version: "2.1.5" - path_provider_android: - dependency: transitive - description: - name: path_provider_android - sha256: "993381400e94d18469750e5b9dcb8206f15bc09f9da86b9e44a9b0092a0066db" - url: "https://pub.dev" - source: hosted - version: "2.2.18" - path_provider_foundation: - dependency: transitive - description: - name: path_provider_foundation - sha256: "16eef174aacb07e09c351502740fa6254c165757638eba1e9116b0a781201bbd" - url: "https://pub.dev" - source: hosted - version: "2.4.2" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.dev" - source: hosted - version: "2.2.1" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.dev" - source: hosted - version: "2.3.0" - permission_handler: - dependency: "direct main" - description: - name: permission_handler - sha256: bc917da36261b00137bbc8896bf1482169cd76f866282368948f032c8c1caae1 - url: "https://pub.dev" - source: hosted - version: "12.0.1" - permission_handler_android: - dependency: transitive - description: - name: permission_handler_android - sha256: "1e3bc410ca1bf84662104b100eb126e066cb55791b7451307f9708d4007350e6" - url: "https://pub.dev" - source: hosted - version: "13.0.1" - permission_handler_apple: - dependency: transitive - description: - name: permission_handler_apple - sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023 - url: "https://pub.dev" - source: hosted - version: "9.4.7" - permission_handler_html: - dependency: transitive - description: - name: permission_handler_html - sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24" - url: "https://pub.dev" - source: hosted - version: "0.1.3+5" - permission_handler_platform_interface: - dependency: transitive - description: - name: permission_handler_platform_interface - sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878 - url: "https://pub.dev" - source: hosted - version: "4.3.0" - permission_handler_windows: - dependency: transitive - description: - name: permission_handler_windows - sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" - url: "https://pub.dev" - source: hosted - version: "0.2.1" - petitparser: - dependency: transitive - description: - name: petitparser - sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" - url: "https://pub.dev" - source: hosted - version: "6.1.0" - platform: - dependency: transitive - description: - name: platform - sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.dev" - source: hosted - version: "3.1.6" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.dev" - source: hosted - version: "2.1.8" - posix: - dependency: transitive - description: - name: posix - sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" - url: "https://pub.dev" - source: hosted - version: "6.0.3" - provider: - dependency: "direct main" - description: - name: provider - sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" - url: "https://pub.dev" - source: hosted - version: "6.1.5+1" - rrule: - dependency: transitive - description: - name: rrule - sha256: b7425410c594d4b6717c9f17ec8ef83c9d1ff2e513c428a135b5924fc2e8e045 - url: "https://pub.dev" - source: hosted - version: "0.2.17" - rxdart: - dependency: transitive - description: - name: rxdart - sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" - url: "https://pub.dev" - source: hosted - version: "0.28.0" - sanitize_html: - dependency: transitive - description: - name: sanitize_html - sha256: "12669c4a913688a26555323fb9cec373d8f9fbe091f2d01c40c723b33caa8989" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - share_plus: - dependency: "direct main" - description: - name: share_plus - sha256: d7dc0630a923883c6328ca31b89aa682bacbf2f8304162d29f7c6aaff03a27a1 - url: "https://pub.dev" - source: hosted - version: "11.1.0" - share_plus_platform_interface: - dependency: transitive - description: - name: share_plus_platform_interface - sha256: "88023e53a13429bd65d8e85e11a9b484f49d4c190abbd96c7932b74d6927cc9a" - url: "https://pub.dev" - source: hosted - version: "6.1.0" - shared_preferences: - dependency: "direct main" - description: - name: shared_preferences - sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" - url: "https://pub.dev" - source: hosted - version: "2.5.3" - shared_preferences_android: - dependency: transitive - description: - name: shared_preferences_android - sha256: a2608114b1ffdcbc9c120eb71a0e207c71da56202852d4aab8a5e30a82269e74 - url: "https://pub.dev" - source: hosted - version: "2.4.12" - shared_preferences_foundation: - dependency: transitive - description: - name: shared_preferences_foundation - sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" - url: "https://pub.dev" - source: hosted - version: "2.5.4" - shared_preferences_linux: - dependency: transitive - description: - name: shared_preferences_linux - sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - shared_preferences_platform_interface: - dependency: transitive - description: - name: shared_preferences_platform_interface - sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - shared_preferences_web: - dependency: transitive - description: - name: shared_preferences_web - sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 - url: "https://pub.dev" - source: hosted - version: "2.4.3" - shared_preferences_windows: - dependency: transitive - description: - name: shared_preferences_windows - sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - shimmer: - dependency: "direct main" - description: - name: shimmer - sha256: "5f88c883a22e9f9f299e5ba0e4f7e6054857224976a5d9f839d4ebdc94a14ac9" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - sizer: - dependency: "direct main" - description: - name: sizer - sha256: "9963c89e4d30d7c2108de3eafc0a7e6a4a8009799376ea6be5ef0a9ad87cfbad" - url: "https://pub.dev" - source: hosted - version: "3.1.3" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - smooth_corner: - dependency: "direct main" - description: - name: smooth_corner - sha256: "112d7331f82ead81ec870c5d1eb0624f2e7e367eccd166c2fffe4c11d4f87c4f" - url: "https://pub.dev" - source: hosted - version: "1.1.1" - source_span: - dependency: transitive - description: - name: source_span - sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" - url: "https://pub.dev" - source: hosted - version: "1.10.1" - sprintf: - dependency: transitive - description: - name: sprintf - sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" - url: "https://pub.dev" - source: hosted - version: "7.0.0" - sqflite: - dependency: transitive - description: - name: sqflite - sha256: e2297b1da52f127bc7a3da11439985d9b536f75070f3325e62ada69a5c585d03 - url: "https://pub.dev" - source: hosted - version: "2.4.2" - sqflite_android: - dependency: transitive - description: - name: sqflite_android - sha256: "2b3070c5fa881839f8b402ee4a39c1b4d561704d4ebbbcfb808a119bc2a1701b" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - sqflite_common: - dependency: transitive - description: - name: sqflite_common - sha256: "84731e8bfd8303a3389903e01fb2141b6e59b5973cacbb0929021df08dddbe8b" - url: "https://pub.dev" - source: hosted - version: "2.5.5" - sqflite_darwin: - dependency: transitive - description: - name: sqflite_darwin - sha256: "279832e5cde3fe99e8571879498c9211f3ca6391b0d818df4e17d9fff5c6ccb3" - url: "https://pub.dev" - source: hosted - version: "2.4.2" - sqflite_platform_interface: - dependency: transitive - description: - name: sqflite_platform_interface - sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" - url: "https://pub.dev" - source: hosted - version: "2.4.0" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.dev" - source: hosted - version: "1.12.1" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - stream_transform: - dependency: transitive - description: - name: stream_transform - sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 - url: "https://pub.dev" - source: hosted - version: "2.1.1" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" - source: hosted - version: "1.4.1" - syncfusion_flutter_calendar: - dependency: "direct main" - description: - name: syncfusion_flutter_calendar - sha256: "8e8a4eef01d6a82ae2c17e76d497ff289ded274de014c9f471ffabc12d1e2e71" - url: "https://pub.dev" - source: hosted - version: "30.2.7" - syncfusion_flutter_core: - dependency: transitive - description: - name: syncfusion_flutter_core - sha256: bfd026c0f9822b49ff26fed11cd3334519acb6a6ad4b0c81d9cd18df6af1c4c0 - url: "https://pub.dev" - source: hosted - version: "30.2.7" - syncfusion_flutter_datepicker: - dependency: transitive - description: - name: syncfusion_flutter_datepicker - sha256: b5f35cc808e91b229d41613efe71dadab1549a35bfd493f922fc06ccc2fe908c - url: "https://pub.dev" - source: hosted - version: "30.2.7" - syncfusion_localizations: - dependency: transitive - description: - name: syncfusion_localizations - sha256: bb32b07879b4c1dee5d4c8ad1c57343a4fdae55d65a87f492727c11b68f23164 - url: "https://pub.dev" - source: hosted - version: "30.2.7" - synchronized: - dependency: transitive - description: - name: synchronized - sha256: "0669c70faae6270521ee4f05bffd2919892d42d1276e6c495be80174b6bc0ef6" - url: "https://pub.dev" - source: hosted - version: "3.3.1" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" - source: hosted - version: "1.2.2" - test_api: - dependency: transitive - description: - name: test_api - sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" - url: "https://pub.dev" - source: hosted - version: "0.7.6" - time: - dependency: transitive - description: - name: time - sha256: "370572cf5d1e58adcb3e354c47515da3f7469dac3a95b447117e728e7be6f461" - url: "https://pub.dev" - source: hosted - version: "2.1.5" - timezone: - dependency: transitive - description: - name: timezone - sha256: dd14a3b83cfd7cb19e7888f1cbc20f258b8d71b54c06f79ac585f14093a287d1 - url: "https://pub.dev" - source: hosted - version: "0.10.1" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - url_launcher: - dependency: "direct main" - description: - name: url_launcher - sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 - url: "https://pub.dev" - source: hosted - version: "6.3.2" - url_launcher_android: - dependency: transitive - description: - name: url_launcher_android - sha256: "69ee86740f2847b9a4ba6cffa74ed12ce500bbe2b07f3dc1e643439da60637b7" - url: "https://pub.dev" - source: hosted - version: "6.3.18" - url_launcher_ios: - dependency: transitive - description: - name: url_launcher_ios - sha256: d80b3f567a617cb923546034cc94bfe44eb15f989fe670b37f26abdb9d939cb7 - url: "https://pub.dev" - source: hosted - version: "6.3.4" - url_launcher_linux: - dependency: transitive - description: - name: url_launcher_linux - sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" - url: "https://pub.dev" - source: hosted - version: "3.2.1" - url_launcher_macos: - dependency: transitive - description: - name: url_launcher_macos - sha256: c043a77d6600ac9c38300567f33ef12b0ef4f4783a2c1f00231d2b1941fea13f - url: "https://pub.dev" - source: hosted - version: "3.2.3" - url_launcher_platform_interface: - dependency: transitive - description: - name: url_launcher_platform_interface - sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" - url: "https://pub.dev" - source: hosted - version: "2.3.2" - url_launcher_web: - dependency: transitive - description: - name: url_launcher_web - sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - url_launcher_windows: - dependency: transitive - description: - name: url_launcher_windows - sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" - url: "https://pub.dev" - source: hosted - version: "3.1.4" - uuid: - dependency: "direct main" - description: - name: uuid - sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff - url: "https://pub.dev" - source: hosted - version: "4.5.1" - vector_graphics: - dependency: transitive - description: - name: vector_graphics - sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6 - url: "https://pub.dev" - source: hosted - version: "1.1.19" - vector_graphics_codec: - dependency: transitive - description: - name: vector_graphics_codec - sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" - url: "https://pub.dev" - source: hosted - version: "1.1.13" - vector_graphics_compiler: - dependency: transitive - description: - name: vector_graphics_compiler - sha256: d354a7ec6931e6047785f4db12a1f61ec3d43b207fc0790f863818543f8ff0dc - url: "https://pub.dev" - source: hosted - version: "1.1.19" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b - url: "https://pub.dev" - source: hosted - version: "2.2.0" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" - url: "https://pub.dev" - source: hosted - version: "14.3.1" - web: - dependency: "direct main" - description: - name: web - sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.dev" - source: hosted - version: "1.1.1" - win32: - dependency: transitive - description: - name: win32 - sha256: "329edf97fdd893e0f1e3b9e88d6a0e627128cc17cc316a8d67fda8f1451178ba" - url: "https://pub.dev" - source: hosted - version: "5.13.0" - win32_registry: - dependency: transitive - description: - name: win32_registry - sha256: "6f1b564492d0147b330dd794fee8f512cec4977957f310f9951b5f9d83618dae" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - xml: - dependency: transitive - description: - name: xml - sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 - url: "https://pub.dev" - source: hosted - version: "6.5.0" -sdks: - dart: ">=3.8.0-0 <4.0.0" - flutter: ">=3.29.0" diff --git a/pubspec.yaml b/pubspec.yaml index 1263e33..7772ad5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -33,10 +33,10 @@ dependencies: provider: ^6.1.5+1 get_it: ^8.2.0 just_audio: ^0.10.4 -# flutter_callkit_incoming: -# git: -# url: https://github.com/hiennguyen92/flutter_callkit_incoming.git -# ref: dev + # flutter_callkit_incoming: + # git: + # url: https://github.com/hiennguyen92/flutter_callkit_incoming.git + # ref: dev url_launcher: ^6.3.2 logger: ^2.6.1 lottie: ^3.3.1 @@ -64,6 +64,8 @@ dependencies: equatable: ^2.0.7 google_api_availability: ^5.0.1 firebase_analytics: ^11.5.1 + jiffy: ^6.4.3 + hijri_gregorian_calendar: ^0.0.4 web: any flutter_staggered_animations: ^1.1.1 @@ -90,24 +92,24 @@ flutter: fonts: - family: Poppins fonts: -# - asset: assets/fonts/poppins/Poppins-Black.ttf -# weight: 900 -# - asset: assets/fonts/poppins/Poppins-ExtraBold.ttf -# weight: 800 -# - asset: assets/fonts/poppins/Poppins-Bold.ttf -# weight: 700 + # - asset: assets/fonts/poppins/Poppins-Black.ttf + # weight: 900 + # - asset: assets/fonts/poppins/Poppins-ExtraBold.ttf + # weight: 800 + # - asset: assets/fonts/poppins/Poppins-Bold.ttf + # weight: 700 - asset: assets/fonts/poppins/Poppins-SemiBold.ttf weight: 600 - asset: assets/fonts/poppins/Poppins-Medium.ttf weight: 500 - asset: assets/fonts/poppins/Poppins-Regular.ttf weight: 400 -# - asset: assets/fonts/poppins/Poppins-Light.ttf -# weight: 300 -# - asset: assets/fonts/poppins/Poppins-ExtraLight.ttf -# weight: 200 -# - asset: assets/fonts/poppins/Poppins-Thin.ttf -# weight: 100 + # - asset: assets/fonts/poppins/Poppins-Light.ttf + # weight: 300 + # - asset: assets/fonts/poppins/Poppins-ExtraLight.ttf + # weight: 200 + # - asset: assets/fonts/poppins/Poppins-Thin.ttf + # weight: 100 - family: GESSTwo