# Conflicts:
#	lib/presentation/insurance/insurance_home_page.dart
pull/14/head
Sultan khan 2 months ago
commit 7919d40f65

@ -0,0 +1,4 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.26704 17.0625C7.11121 17.0625 5.9391 17.0625 5.2024 16.9854C4.44534 16.9062 3.79943 16.7389 3.24085 16.3439C2.94808 16.1369 2.68667 15.8903 2.46528 15.6109C2.03791 15.0716 1.85547 14.4432 1.76989 13.7132C1.68747 13.0102 1.68748 12.1307 1.6875 11.0446L1.6875 9.10701C1.6875 8.04332 1.6875 7.20881 1.73189 6.53328C1.77708 5.84565 1.87048 5.27212 2.08131 4.73815C2.71386 3.1361 4.04416 1.88905 5.70916 1.30241C6.74599 0.937106 8.01098 0.937263 10.1407 0.937534C11.3069 0.937127 12.411 0.936836 13.0551 1.16377C14.0875 1.52753 14.9188 2.30323 15.3154 3.30771C15.4529 3.65583 15.5096 4.02009 15.5365 4.42856C15.5625 4.82499 15.5625 5.31066 15.5625 5.91003V8.26973C15.5625 8.67305 15.2355 9 14.8322 9C14.4289 9 14.102 8.67305 14.102 8.26973V5.93492C14.102 5.30472 14.1016 4.86751 14.0791 4.52501C14.057 4.18904 14.0159 3.99523 13.9576 3.84775C13.7251 3.25872 13.2258 2.77749 12.5713 2.5469C12.1938 2.41389 11.6935 2.40342 10.3179 2.40342C10.0943 2.40342 9.82675 2.4043 9.57313 2.40544C9.31951 2.40659 8.90446 2.40846 8.55785 2.61013C8.3293 2.74312 8.16373 2.89454 8.06871 3.05998C7.9057 3.34379 7.81241 3.64914 7.81241 3.9999L7.83978 4.78018C7.8457 5.06525 7.83669 5.3979 7.75065 5.71901C7.58306 6.34449 7.0945 6.83305 6.46902 7.00064C6.14791 7.08669 5.81526 7.09569 5.53018 7.08977L4.74991 7.0624C4.41491 7.0624 4.09976 7.14742 3.82488 7.29707C3.65429 7.38993 3.48823 7.57226 3.35853 7.79049C3.14807 8.14462 3.14794 8.62354 3.14795 8.82381L3.14802 10.9989C3.14802 12.1415 3.1492 12.9345 3.22039 13.5419C3.28957 14.1319 3.41665 14.4565 3.60832 14.6984C3.74167 14.8667 3.90095 15.0175 4.08204 15.1456C4.35042 15.3353 4.71336 15.4604 5.3538 15.5274C6.00588 15.5956 7.06057 15.5966 8.26704 15.5966C8.67184 15.5966 9 15.9247 9 16.3296C9 16.7344 8.67184 17.0625 8.26704 17.0625Z" fill="#8F9AA3"/>
<path d="M12.3737 9.18753C11.7129 9.18753 11.181 9.40076 10.7414 9.61709C10.5956 9.6889 10.4675 9.75603 10.35 9.81766C10.0849 9.95665 9.87309 10.0677 9.6297 10.1415C9.47677 10.1878 9.32171 10.2348 9.21338 10.2752C9.11899 10.3103 8.94856 10.3771 8.81729 10.5157C8.7011 10.6383 8.64553 10.7732 8.61318 10.8809C8.58617 10.9708 8.56326 11.0918 8.54641 11.1808C8.08141 13.6308 9.10597 15.9887 11.6102 16.8995C11.8405 16.9834 12.0578 17.0625 12.3748 17.0625C12.6919 17.0625 12.9092 16.9834 13.1395 16.8995C15.6437 15.9886 16.6672 13.6306 16.2021 11.1808C16.1852 11.0918 16.1623 10.9707 16.1353 10.8808C16.103 10.7732 16.0474 10.6383 15.9311 10.5156C15.7999 10.377 15.6294 10.3102 15.535 10.2751C15.4267 10.2348 15.2716 10.1878 15.1187 10.1415C14.8752 10.0677 14.6631 9.9566 14.3978 9.81757C14.2802 9.75594 14.1522 9.68884 14.0063 9.61706C13.5665 9.40075 13.0344 9.18753 12.3737 9.18753Z" fill="#8F9AA3"/>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@ -0,0 +1,4 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.51704 17.0625C6.36121 17.0625 5.9391 17.0625 5.2024 16.9854C4.44534 16.9062 3.79943 16.7389 3.24085 16.3439C2.94808 16.1369 2.68667 15.8903 2.46528 15.6109C2.03791 15.0716 1.85547 14.4432 1.76989 13.7132C1.68747 13.0102 1.68748 12.1307 1.6875 11.0446L1.6875 9.10701C1.6875 8.04332 1.6875 7.20881 1.73189 6.53328C1.77708 5.84565 1.87048 5.27212 2.08131 4.73815C2.71386 3.1361 4.04416 1.88905 5.70916 1.30241C6.74599 0.937106 8.01098 0.937263 10.1407 0.937534C11.3069 0.937127 12.411 0.936836 13.0551 1.16377C14.0875 1.52753 14.9188 2.30323 15.3154 3.30771C15.4529 3.65583 15.5096 4.02009 15.5365 4.42856C15.5625 4.82499 15.5625 5.31066 15.5625 5.91003V8.26973C15.5625 8.67305 15.2355 9 14.8322 9C14.4289 9 14.102 8.67305 14.102 8.26973V5.93492C14.102 5.30472 14.1016 4.86751 14.0791 4.52501C14.057 4.18904 14.0159 3.99523 13.9576 3.84775C13.7251 3.25872 13.2258 2.77749 12.5713 2.5469C12.1938 2.41389 11.6935 2.40342 10.3179 2.40342C10.0943 2.40342 9.82675 2.4043 9.57313 2.40544C9.31951 2.40659 8.90446 2.40846 8.55785 2.61013C8.3293 2.74312 8.16373 2.89454 8.06871 3.05998C7.9057 3.34379 7.81241 3.64914 7.81241 3.9999L7.83978 4.78018C7.8457 5.06525 7.83669 5.3979 7.75065 5.71901C7.58306 6.34449 7.0945 6.83305 6.46902 7.00064C6.14791 7.08669 5.81526 7.09569 5.53018 7.08977L4.74991 7.0624C4.41491 7.0624 4.09976 7.14742 3.82488 7.29707C3.65429 7.38993 3.48823 7.57226 3.35853 7.79049C3.14807 8.14462 3.14794 8.62354 3.14795 8.82381L3.14802 10.9989C3.14802 12.1415 3.1492 12.9345 3.22039 13.5419C3.28957 14.1319 3.41665 14.4565 3.60832 14.6984C3.74167 14.8667 3.90095 15.0175 4.08204 15.1456C4.35042 15.3353 4.71336 15.4604 5.3538 15.5274C6.00588 15.5956 6.31057 15.5966 7.51704 15.5966C7.92184 15.5966 8.25 15.9247 8.25 16.3296C8.25 16.7344 7.92184 17.0625 7.51704 17.0625Z" fill="#8F9AA3"/>
<path d="M13.4633 9.98792C13.2634 9.58309 12.9024 9.18753 12.375 9.18753C11.8482 9.18753 11.4863 9.58226 11.2848 9.98649L10.6925 11.1809C10.6722 11.2217 10.6319 11.237 10.6143 11.2395L9.54899 11.418C9.10502 11.4926 8.64096 11.7274 8.48559 12.218C8.3309 12.7064 8.5719 13.1659 8.88821 13.4849L9.71995 14.3235C9.73567 14.3342 9.76362 14.3708 9.7497 14.4315L9.51213 15.4672C9.40639 15.928 9.40686 16.5325 9.87131 16.8742C10.3385 17.2179 10.9155 17.0328 11.3208 16.7904L12.3212 16.1933C12.3668 16.1661 12.4113 16.1813 12.4279 16.1923L13.4302 16.7905C13.8344 17.0313 14.4127 17.2194 14.8805 16.8756C15.346 16.5335 15.3437 15.9272 15.2387 15.4677L15.001 14.4315C14.9884 14.3763 15.0156 14.3365 15.0308 14.3235L15.8612 13.4862L15.8619 13.4855C16.1802 13.1664 16.4221 12.7063 16.2661 12.217C16.1099 11.7269 15.6454 11.4925 15.202 11.418L14.1337 11.239C14.0902 11.2318 14.063 11.1972 14.0549 11.1808L13.4633 9.98792Z" fill="#8F9AA3"/>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

@ -0,0 +1,5 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.7493 12.75C12.7493 13.1643 12.4135 13.5 11.9993 13.5H6.74927C6.33505 13.5 5.99927 13.1643 5.99927 12.75C5.99927 12.3358 6.33505 12 6.74927 12L11.9993 12C12.4135 12 12.7493 12.3358 12.7493 12.75Z" fill="#8F9AA3"/>
<path d="M11.9993 10.5C12.4135 10.5 12.7493 10.1643 12.7493 9.75005C12.7493 9.33583 12.4135 9.00005 11.9993 9.00005H9.74927C9.33506 9.00005 8.99927 9.33583 8.99927 9.75004C8.99927 10.1643 9.33506 10.5 9.74927 10.5H11.9993Z" fill="#8F9AA3"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.57667 16.9854C6.31336 17.0625 7.23796 17.0625 8.39379 17.0625H9.05029C10.47 17.0625 11.6054 17.0625 12.4965 16.9493C13.4148 16.8327 14.1838 16.5847 14.798 16.0046C15.4184 15.4185 15.6894 14.6746 15.8158 13.7866C15.9368 12.9363 15.9368 11.8564 15.9368 10.5224V5.91003C15.9368 5.31066 15.9368 4.82499 15.9107 4.42856C15.8839 4.02009 15.8272 3.65583 15.6897 3.30771C15.2931 2.30323 14.4618 1.52753 13.4294 1.16377C12.7853 0.936835 11.6812 0.937127 10.515 0.937534C8.38525 0.937264 7.12025 0.937105 6.08343 1.30241C4.41843 1.88904 3.08813 3.1361 2.45558 4.73815C2.24475 5.27212 2.15135 5.84565 2.10616 6.53328C2.06176 7.20882 2.06177 8.04328 2.06177 9.10699L2.06177 11.0446C2.06175 12.1307 2.06174 13.0102 2.14415 13.7132C2.22974 14.4432 2.41218 15.0716 2.83955 15.6109C3.06094 15.8903 3.32235 16.1369 3.61512 16.3439C4.17369 16.7389 4.81961 16.9062 5.57667 16.9854ZM13.797 14.9371C13.5021 15.2156 13.085 15.397 12.3131 15.495C11.5245 15.5952 10.4818 15.5965 8.99926 15.5965H8.43496C7.2285 15.5965 6.38015 15.5956 5.72807 15.5274C5.08762 15.4604 4.72468 15.3353 4.45631 15.1456C4.27522 15.0175 4.11594 14.8667 3.98259 14.6984C3.79092 14.4565 3.66384 14.1319 3.59466 13.5418C3.52346 12.9345 3.52228 12.1415 3.52228 10.9989L3.52222 8.82381C3.52221 8.62354 3.52234 8.14462 3.7328 7.79049C3.8625 7.57226 4.02856 7.38993 4.19915 7.29707C4.47403 7.14742 4.78918 7.0624 5.12418 7.0624L5.90445 7.08977C6.18952 7.09569 6.52218 7.08668 6.84329 7.00064C7.46877 6.83305 7.95732 6.34449 8.12492 5.71901C8.21096 5.3979 8.21996 5.06525 8.21405 4.78018L8.18668 3.9999C8.18668 3.64913 8.27997 3.34379 8.44298 3.05998C8.538 2.89454 8.70357 2.74312 8.93212 2.61014C9.27873 2.40845 9.69378 2.40658 9.9474 2.40544C10.201 2.4043 10.4686 2.40342 10.6921 2.40342C12.0677 2.40342 12.5681 2.41389 12.9456 2.5469C13.6001 2.77749 14.0993 3.25872 14.3319 3.84775C14.3901 3.99523 14.4313 4.18904 14.4534 4.52501C14.4759 4.86751 14.4762 5.30472 14.4762 5.93492V10.4659C14.4762 11.8699 14.4745 12.8447 14.3699 13.5792C14.2691 14.2879 14.0856 14.6644 13.797 14.9371Z" fill="#8F9AA3"/>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

@ -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

@ -1,7 +1,6 @@
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
@ -9,7 +8,6 @@ import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/services/analytics/analytics_service.dart';
import 'package:hmg_patient_app_new/services/dialog_service.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
import 'package:http/http.dart' as http;
@ -19,7 +17,7 @@ abstract class ApiClient {
Future<void> post(
String endPoint, {
required Map<String, dynamic> body,
required Function(dynamic response, int statusCode, {int? messageStatus}) onSuccess,
required Function(dynamic response, int statusCode, {int? messageStatus, String? errorMessage}) onSuccess,
required Function(String error, int statusCode, {int? messageStatus, Failure? failureType}) onFailure,
bool isAllowAny,
bool isExternal,
@ -77,29 +75,26 @@ abstract class ApiClient {
class ApiClientImp implements ApiClient {
final _analytics = getIt<GAnalytics>();
final LoggerService loggerService;
final AppState appState;
final DialogService dialogService;
final LoggerService _loggerService;
final AppState _appState;
ApiClientImp({
required this.loggerService,
required this.dialogService,
required this.appState,
});
required LoggerService loggerService,
required AppState appState,
}) : _appState = appState,
_loggerService = loggerService;
@override
post(
String endPoint, {
required Map<String, dynamic> body,
required Function(dynamic response, int statusCode, {int? messageStatus}) onSuccess,
required Function(dynamic response, int statusCode, {int? messageStatus, String? errorMessage}) onSuccess,
required Function(String error, int statusCode, {int? messageStatus, Failure? failureType}) onFailure,
bool isAllowAny = false,
bool isAllowAny = true,
bool isExternal = false,
bool isRCService = false,
bool bypassConnectionCheck = false,
}) async {
AppState appState = getIt.get<AppState>();
String url;
if (isExternal) {
url = endPoint;
@ -111,39 +106,19 @@ class ApiClientImp implements ApiClient {
}
}
try {
var user = appState.getAuthenticatedUser;
var user = _appState.getAuthenticatedUser;
Map<String, String> headers = {'Content-Type': 'application/json', 'Accept': 'application/json'};
if (!isExternal) {
String? token = appState.appAuthToken;
String? languageID = (appState.postParamsObject?.languageID == 1 ? 'ar' : 'en');
if (endPoint == ApiConsts.sendActivationCode) {
languageID = 'en';
}
String? token = _appState.appAuthToken;
if (body.containsKey('SetupID')) {
body['SetupID'] = body.containsKey('SetupID') ? body['SetupID'] ?? body[''] : SETUP_ID;
} else {}
if (body.containsKey('LanguageID')) {
if (body['LanguageID'] != null) {
body['LanguageID'] = body['LanguageID'] == 'ar'
? 1
: body['LanguageID'] == 'en'
? 2
: body['LanguageID'];
}
}
if (body.containsKey('isDentalAllowedBackend')) {
body['isDentalAllowedBackend'] = body.containsKey('isDentalAllowedBackend') ? body['isDentalAllowedBackend'] ?? IS_DENTAL_ALLOWED_BACKEND : IS_DENTAL_ALLOWED_BACKEND;
}
//Todo: I have converted it to string
body['DeviceTypeID'] = Platform.isIOS
? "1"
: await Utils.isGoogleServicesAvailable()
? "2"
: "3";
if (!body.containsKey('IsPublicRequest')) {
// if (!body.containsKey('PatientType')) {
if (user != null && user.patientType != null) {
@ -158,6 +133,7 @@ class ApiClientImp implements ApiClient {
body['PatientType'] = PATIENT_TYPE_ID.toString();
}
// TODO : These should be from the appState
if (user != null) {
body['TokenID'] = body['TokenID'] ?? token;
body['PatientID'] = body['PatientID'] ?? user.patientID;
@ -175,129 +151,134 @@ class ApiClientImp implements ApiClient {
// request.languageID = (languageID == 'ar' ? 1 : 2);
// request.patientOutSA = (request.zipCode == '966' || request.zipCode == '+966') ? 0 : 1;
// TODO : we will use all these from appState
body['LanguageID'] = body['LanguageID'] ?? "2";
body['VersionID'] = body['VersionID'] ?? "50.0";
body['Channel'] = body['Channel'] ?? "3";
body['IPAdress'] = body['IPAdress'] ?? "10.20.10.20";
body['generalid'] = body['generalid'] ?? "Cs2020@2016\$2958";
body['Latitude'] = body['Latitude'] ?? "0.0";
body['Longitude'] = body['Longitude'] ?? "0.0";
body['DeviceTypeID'] = body['DeviceTypeID'] ??
(Platform.isIOS
? "1"
: await Utils.isGoogleServicesAvailable()
? "2"
: "3");
body['TokenID'] = "@dm!n";
body['VersionID'] = ApiConsts.appVersionID.toString();
body['Channel'] = ApiConsts.appChannelId.toString();
body['IPAdress'] = ApiConsts.appIpAddress;
body['generalid'] = ApiConsts.appGeneralId;
body['LanguageID'] = _appState.getLanguageID().toString();
body['Latitude'] = _appState.userLat.toString();
body['Longitude'] = _appState.userLong.toString();
body['DeviceTypeID'] = _appState.deviceTypeID;
if (_appState.appLoginTokenID.isNotEmpty) {
body['LogInTokenID'] = _appState.appLoginTokenID;
}
body.removeWhere((key, value) => value == null);
log("body: ${json.encode(body)}");
log("uri: ${Uri.parse(url.trim())}");
if (await Utils.checkConnection(bypassConnectionCheck: bypassConnectionCheck)) {
final response = await http.post(Uri.parse(url.trim()), body: json.encode(body), headers: headers);
final bool networkStatus = await Utils.checkConnection(bypassConnectionCheck: bypassConnectionCheck);
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);

@ -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<String, String> packagesAuthHeader = {};
}
static final String sendActivationCode = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationType';
static final String sendActivationCodeRegister = 'Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationTypeForRegistration';
static final String checkActivationCode = 'Services/Authentication.svc/REST/CheckActivationCode';
static final String checkActivationCodeRegister = 'Services/Authentication.svc/REST/CheckActivationCodeForRegistration';
// static values for Api
static final double appVersionID = 18.7;
static final int appChannelId = 3;
static final String appIpAddress = "10.20.10.20";
static final String appGeneralId = "Cs2020@2016\$2958";
}

@ -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';

@ -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<String, dynamic> 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;
}

@ -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';
}

@ -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';
}

@ -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<LoggerService>(() => LoggerServiceImp(logger: logger));
getIt.registerLazySingleton<FirebaseService>(() => FirebaseServiceImpl(
loggerService: getIt(),
appState: getIt(),
firebaseMessaging: FirebaseMessaging.instance,
));
getIt.registerLazySingleton<NavigationService>(() => NavigationService());
getIt.registerLazySingleton<GAnalytics>(() => GAnalytics());
getIt.registerLazySingleton<AppState>(() => AppState(navigationService: getIt()));
@ -56,8 +64,8 @@ class AppDependencies {
));
final sharedPreferences = await SharedPreferences.getInstance();
getIt.registerLazySingleton<CacheService>(() => CacheServiceImp(sharedPreferences: sharedPreferences));
getIt.registerLazySingleton<ApiClient>(() => ApiClientImp(loggerService: getIt(), dialogService: getIt(), appState: getIt()));
getIt.registerLazySingleton<CacheService>(() => CacheServiceImp(sharedPreferences: sharedPreferences, loggerService: getIt()));
getIt.registerLazySingleton<ApiClient>(() => ApiClientImp(loggerService: getIt(), appState: getIt()));
// Repositories
getIt.registerLazySingleton<CommonRepo>(() => CommonRepoImp(loggerService: getIt()));
@ -103,6 +111,8 @@ class AppDependencies {
getIt.registerLazySingleton<AuthenticationViewModel>(
() => AuthenticationViewModel(
authenticationRepo: getIt(),
cacheService: getIt(),
navigationService: getIt(),
dialogService: getIt(),
appState: getIt(),
errorHandlerService: getIt(),

@ -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) {

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

@ -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;

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

@ -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<Map<Permission, PermissionStatus>> 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<void> _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<void>(
// 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<GAnalytics>().appointment.appointment_reminder_time(reminde_before: text);
// },
// ),
// );
// },
// );
// }
static Future<CalendarUtils> getInstance() async {
tzl.initializeTimeZones();
if (_completer != null) {

@ -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<NavigationService>();
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;
}
}

@ -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<void> requestPermissions() async {
try {
if (Platform.isIOS) {
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(alert: true, badge: true, sound: true);
await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()?.requestPermissions(alert: true, badge: true, sound: true);
} else if (Platform.isAndroid) {
Map<Permission, PermissionStatus> statuses = await [
Permission.notification,

@ -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;

@ -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;

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

@ -0,0 +1,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<DialogService>();
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;
}
}

@ -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));
}
}

@ -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 = ""}) {

@ -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<Either<Failure, GenericApiModel<dynamic>>> checkPatientAuthentication({
required CheckPatientAuthenticationReq checkPatientAuthenticationReq,
Future<Either<Failure, GenericApiModel<dynamic>>> checkPatientAuthentication({required dynamic checkPatientAuthenticationReq});
Future<Either<Failure, GenericApiModel<dynamic>>> sendActivationCodeRepo({
required dynamic sendActivationCodeReq,
String? languageID,
bool isRegister = false,
});
Future<Either<Failure, GenericApiModel<dynamic>>> sendActivationCodeRegister({required CheckPatientAuthenticationReq checkPatientAuthenticationReq, String? languageID});
Future<Either<Failure, GenericApiModel<dynamic>>> 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<SelectDeviceByImeiRespModelElement>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
errorMessage: errorMessage,
data: model,
);
} catch (e) {
@ -70,33 +75,26 @@ class AuthenticationRepoImp implements AuthenticationRepo {
@override
Future<Either<Failure, GenericApiModel<dynamic>>> checkPatientAuthentication({
required CheckPatientAuthenticationReq checkPatientAuthenticationReq,
required dynamic checkPatientAuthenticationReq,
String? languageID,
}) async {
int isOutKsa = (checkPatientAuthenticationReq.zipCode == '966' || checkPatientAuthenticationReq.zipCode == '+966') ? 0 : 1;
//TODO : We will use all these from AppState directly in the ApiClient
checkPatientAuthenticationReq.versionID = VERSION_ID;
checkPatientAuthenticationReq.channel = CHANNEL;
checkPatientAuthenticationReq.iPAdress = IP_ADDRESS;
checkPatientAuthenticationReq.generalid = GENERAL_ID;
checkPatientAuthenticationReq.languageID = (languageID == 'ar' ? 1 : 2);
checkPatientAuthenticationReq.patientOutSA = isOutKsa;
try {
GenericApiModel<dynamic>? apiResponse;
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<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
errorMessage: errorMessage,
data: response,
);
} catch (e) {
@ -113,41 +111,86 @@ class AuthenticationRepoImp implements AuthenticationRepo {
}
@override
Future<Either<Failure, GenericApiModel<dynamic>>> 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<Either<Failure, GenericApiModel<dynamic>>> 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<dynamic>? 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<dynamic>(
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<Either<Failure, GenericApiModel<dynamic>>> 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<dynamic>? 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<dynamic>(
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!);

@ -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<NationalityCountries>? 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<void> 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<void> selectDeviceImei({Function(dynamic)? onSuccess, Function(String)? onError}) async {
String firebaseToken = "dOGRRszQQMGe_9wA5Hx3kO:APA91bFV5IcIJXvcCXXk0tc2ddtZgWwCPq7sGSuPr-YW7iiJpQZKgFGN9GAzCVOWL8MfheaP1slE8MdxB7lczdPBGdONQ7WbMmhgHcsUCUktq-hsapGXXqc";
final result = await authenticationRepo.selectDeviceByImei(firebaseToken: firebaseToken);
Future<void> 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<void> _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<void> _handleNewImeiRegistration() async {
await selectDeviceImei(onSuccess: (dynamic respData) async {
try {
if (respData != null) {
dynamic data = SelectDeviceByImeiRespModelElement.fromJson(respData.toJson());
_appState.setSelectDeviceByImeiRespModelElement(data);
LoadingUtils.hideFullScreenLoader();
// TODO: Navigate to SavedLogin when available
// SelectDeviceByImeiRespModelElement savedData =
// SelectDeviceByImeiRespModelElement.fromJson(respData);
// navigationService.pushPage(page: SavedLogin(savedData));
_navigationService.pushPage(page: LoginScreen());
} else {
LoadingUtils.hideFullScreenLoader();
_navigationService.pushPage(page: LoginScreen());
}
} catch (e) {
log("Error processing IMEI registration response: $e");
LoadingUtils.hideFullScreenLoader();
_navigationService.pushPage(page: LoginScreen());
}
}, onError: (String error) {
LoadingUtils.hideFullScreenLoader();
_dialogService.showErrorBottomSheet(message: error, onOkPressed: () {});
});
}
Future<void> checkUserAuthentication({required OTPTypeEnum otpTypeEnum, Function(dynamic)? onSuccess, Function(String)? onError}) async {
// TODO: THIS SHOULD BE REMOVED LATER ON AND PASSED FROM APP STATE DIRECTLY INTO API CLIENT. BECAUSE THIS API ONLY NEEDS FEW PARAMS FROM USER
if (phoneNumberController.text.isEmpty) {
phoneNumberController.text = "504278212";
}
bool isValidated = ValidationUtils.isValidatePhoneAndId(
phoneNumber: phoneNumberController.text,
nationalId: nationalIdController.text,
);
if (!isValidated) {
return;
}
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<void> 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<void> 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<void> 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<void> 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<String, dynamic>);
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<String, dynamic>);
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<void> 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<void> onWrongActivationCode({String? message}) async {
// TODO: HANDLE THIS VIA BOTTOM SHEET
}
@override
void dispose() {
nationalIdController.dispose();
phoneNumberController.dispose();
myFocusNode.dispose();
super.dispose();
}
}

@ -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<String, dynamic> 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<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
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;
}
}

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

@ -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<String, dynamic> 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<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
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;

@ -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<OTPVerificationPage> createState() => _OTPVerificationPageState();
State<OTPVerificationScreen> createState() => _OTPVerificationScreenState();
}
class _OTPVerificationPageState extends State<OTPVerificationPage> {
class _OTPVerificationScreenState extends State<OTPVerificationScreen> {
final int _otpLength = 4;
late final List<TextEditingController> _controllers;
late final List<FocusNode> _focusNodes;
@ -41,8 +49,12 @@ class _OTPVerificationPageState extends State<OTPVerificationPage> {
@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();
}

@ -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<Either<Failure, GenericApiModel<List<PatientInsuranceDetailsResponseModel>>>> getPatientInsuranceDetails({required String patientId});
Future<Either<Failure, GenericApiModel<List<PatientInsuranceCardHistoryResponseModel>>>> getPatientInsuranceCardHistory({required String patientId});
Future<Either<Failure, GenericApiModel<PatientInsuranceUpdateResponseModel>>> 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<Either<Failure, GenericApiModel<List<PatientInsuranceCardHistoryResponseModel>>>> 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<List<PatientInsuranceCardHistoryResponseModel>>? 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<String, dynamic>)).toList().cast<PatientInsuranceCardHistoryResponseModel>();
apiResponse = GenericApiModel<List<PatientInsuranceCardHistoryResponseModel>>(
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<Either<Failure, GenericApiModel<PatientInsuranceUpdateResponseModel>>> 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<PatientInsuranceUpdateResponseModel>? 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<PatientInsuranceUpdateResponseModel>(
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()));
}
}
}

@ -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<PatientInsuranceDetailsResponseModel> patientInsuranceList = [];
List<PatientInsuranceCardHistoryResponseModel> 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<void> getPatientInsuranceDetails({Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await insuranceRepo.getPatientInsuranceDetails(patientId: "1231755");
@ -47,4 +67,45 @@ class InsuranceViewModel extends ChangeNotifier {
},
);
}
Future<void> 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<void> 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);
}
}
},
);
}
}

@ -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<String, dynamic> 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<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
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;
}
}

@ -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<String, dynamic> 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<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
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;
}
}

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

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

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

@ -5,7 +5,9 @@ import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart';
import 'package:hmg_patient_app_new/features/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<void> callAppStateInitializations() async {
final String deviceTypeId = (Platform.isIOS
? "1"
: await Utils.isGoogleServicesAvailable()
? "2"
: "3");
AppState appState = getIt.get<AppState>();
appState.setDeviceTypeID = deviceTypeId;
}
Future<void> callInitializations() async {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();
@ -41,6 +53,7 @@ Future<void> 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()),

@ -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<LoginScreen> {
class LoginScreenState extends State<LoginScreen> {
@override
void initState() {
super.initState();
@ -83,7 +88,7 @@ class _LoginScreen extends State<LoginScreen> {
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<LoginScreen> {
);
}
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<LoginScreen> {
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,

@ -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<RegisterNew> {
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<RegisterNew> {
// } else {
// registerUser(1);
// }
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => OTPVerificationPage(phoneNumber: '12234567')));
},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.primaryRedBorderColor,

@ -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<RegisterNewStep2> {
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<RegisterNewStep2> {
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<RegisterNewStep2> {
)
: 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<RegisterNewStep2> {
? Selector<AuthenticationViewModel, ({List<NationalityCountries>? countriesList, NationalityCountries? selectedCountry, bool isArabic})>(
selector: (context, authViewModel) {
final appState = getIt.get<AppState>();
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) {

@ -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';

@ -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<LandingPage> {
@override
Widget build(BuildContext context) {
AppState appState = getIt.get<AppState>();
NavigationService navigationService = getIt.get<NavigationService>();
final AuthenticationViewModel authenticationViewModel = context.read<AuthenticationViewModel>();
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),
],
),
),
);

@ -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),
],
);
}

@ -62,8 +62,9 @@ class _InsuranceHomePageState extends State<InsuranceHomePage> {
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),

@ -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),
),
],
);
});

@ -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<InsuranceViewModel>(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,
),
],
);
}
}

@ -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,

@ -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<MedicalFilePage> createState() => _MedicalFilePageState();
}
class _MedicalFilePageState extends State<MedicalFilePage> {
late InsuranceViewModel insuranceViewModel;
@override
void initState() {
scheduleMicrotask(() {
insuranceViewModel.initInsuranceProvider();
});
super.initState();
}
@override
Widget build(BuildContext context) {
insuranceViewModel = Provider.of<InsuranceViewModel>(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<InsuranceViewModel>(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<InsuranceViewModel>(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),
],
),
),
);

@ -313,6 +313,7 @@ class _PrescriptionDetailPageState extends State<PrescriptionDetailPage> {
SizedBox(width: 12.h),
Switch(
activeColor: AppColors.successColor,
activeTrackColor: AppColors.successColor.withValues(alpha: .15),
value: prescriptionVM.prescriptionDetailsList[index].hasReminder!,
onChanged: (newValue) {
setState(() {

@ -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<String, WidgetBuilder> get routes => {
initialRoute: (context) => SplashPage(),
login: (context) => LoginScreen(),
loginScreen: (context) => LoginScreen(),
};
}

@ -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<void> saveString({required String key, required String value});
Future<void> saveInt({required String key, required int value});
Future<void> saveDouble({required String key, required double value});
Future<void> saveBool({required String key, required bool value});
Future<void> saveStringList({required String key, required List<String> value});
String? getString({required String key});
int? getInt({required String key});
double? getDouble({required String key});
bool? getBool({required String key});
List<String>? getStringList({required String key});
Future<dynamic> getObject({required String key});
Future<void> saveObject({required String key, required dynamic value});
Future<void> remove({required String key});
Future<void> clear();
}
class CacheServiceImp implements CacheService {
SharedPreferences sharedPreferences;
final SharedPreferences sharedPreferences;
final LoggerService loggerService;
CacheServiceImp({
required this.sharedPreferences,
required this.loggerService,
});
@override
Future<void> saveString({required String key, required String value}) async {
await sharedPreferences.setString(key, value);
}
@override
Future<void> saveInt({required String key, required int value}) async {
await sharedPreferences.setInt(key, value);
}
@override
Future<void> saveDouble({required String key, required double value}) async {
await sharedPreferences.setDouble(key, value);
}
@override
Future<void> saveBool({required String key, required bool value}) async {
await sharedPreferences.setBool(key, value);
}
@override
Future<void> saveStringList({required String key, required List<String> 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<String>? getStringList({required String key}) => sharedPreferences.getStringList(key);
@override
Future<void> remove({required String key}) async {
await sharedPreferences.remove(key);
}
CacheServiceImp({required this.sharedPreferences});
@override
Future<dynamic> 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<void> saveObject({required String key, required dynamic value}) async {
try {
await sharedPreferences.setString(key, json.encode(value));
} catch (ex) {
loggerService.errorLogs(ex.toString());
}
}
@override
Future<void> clear() async {
await sharedPreferences.clear();
}
}

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

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

@ -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<String?> 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<String> getDeviceToken() async {
try {
String? deviceToken = await firebaseMessaging.getToken();
appState.setDeviceToken = deviceToken;
return deviceToken ?? "";
} catch (e) {
loggerService.logInfo(e.toString());
return "";
}
}
}

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

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/features/authentication/widgets/otp_verification_screen.dart';
class NavigationService {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
@ -12,4 +13,38 @@ class NavigationService {
void pop<T extends Object?>([T? result]) {
navigatorKey.currentState!.pop(result);
}
void popUntilNamed(String routeName) {
navigatorKey.currentState?.popUntil(ModalRoute.withName(routeName));
}
Future<T?> pushToOtpScreen<T>({
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<T?> pushPage<T>({
required Widget page,
bool fullscreenDialog = false,
bool maintainState = true,
}) {
return navigatorKey.currentState!.push<T>(
MaterialPageRoute(
builder: (_) => page,
fullscreenDialog: fullscreenDialog,
maintainState: maintainState,
),
);
}
}

@ -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<Permission, PermissionStatus> 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();
}
}

@ -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';

@ -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<GenericBottomSheet> {
super.initState();
if (!widget.isForEmail && widget.textController != null) {
widget.textController!.text = widget.initialPhoneNumber!;
widget.textController!.text = widget.initialPhoneNumber ?? "";
}
}

@ -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<CustomTabBarModel> 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<CustomTabBar> {
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();
});
}
}

@ -34,13 +34,13 @@ class TextInputWidget extends StatelessWidget {
final bool hasError;
final String? errorMessage;
Function(CountryEnum)? onCountryChange;
SelectionTypeEnum? selectionType;
final SelectionTypeEnum? selectionType;
// final List<Country> 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) {

File diff suppressed because it is too large Load Diff

@ -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

Loading…
Cancel
Save