Compare commits
	
		
			19 Commits 
		
	
	
		
			fbd6ef0cf8
			...
			5de8314f3f
		
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | 5de8314f3f | 1 month ago | 
|  | b9b0dfd1fa | 1 month ago | 
|  | 15c07cb4e2 | 1 month ago | 
|  | 88f56885ff | 1 month ago | 
|  | 71a07eed8e | 1 month ago | 
|  | 6a4650d658 | 1 month ago | 
|  | ea2d2bf40f | 1 month ago | 
|  | 788887a7f1 | 1 month ago | 
|  | 2174e0e292 | 1 month ago | 
|  | 9c2dd721b4 | 1 month ago | 
|  | f9e7c8988a | 1 month ago | 
|  | 9d852aa281 | 1 month ago | 
|  | b78c78ed8b | 1 month ago | 
|  | a2f60aead1 | 1 month ago | 
|  | 6b766e558d | 1 month ago | 
|  | 286dfaa376 | 1 month ago | 
|  | 2cc331c1c8 | 1 month ago | 
|  | 009fa1859e | 1 month ago | 
|  | fdd5d4cf6d | 1 month ago | 
| @ -0,0 +1,7 @@ | ||||
| <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||||
| <path fill-rule="evenodd" clip-rule="evenodd" d="M17.9973 6.74805C16.4813 6.74805 15.2473 5.51405 15.2473 3.99805C15.2473 2.48205 16.4813 1.24805 17.9973 1.24805C19.5133 1.24805 20.7473 2.48205 20.7473 3.99805C20.7473 5.51405 19.5133 6.74805 17.9973 6.74805ZM17.9973 2.74805C17.3083 2.74805 16.7473 3.30905 16.7473 3.99805C16.7473 4.68705 17.3083 5.24805 17.9973 5.24805C18.6863 5.24805 19.2473 4.68705 19.2473 3.99805C19.2473 3.30905 18.6863 2.74805 17.9973 2.74805Z" fill="#2B353E"/> | ||||
| <path d="M3.9805 22.748C4.0375 22.75 4.0945 22.7501 4.1515 22.7501C5.3445 22.7501 6.31645 22.4411 7.19945 21.7851L7.31242 21.7045C7.39998 21.6421 7.48647 21.5804 7.55453 21.5351C7.65353 21.5731 7.78854 21.6271 7.92054 21.6811L8.07152 21.7421C8.60452 21.9621 9.21954 22.102 9.79554 22.137C11.2485 22.239 12.7885 22.239 14.2485 22.137C18.6245 21.843 22.1965 18.4601 22.7425 14.0921C22.7945 13.6811 22.5025 13.3061 22.0915 13.2551C21.6795 13.2011 21.3055 13.4951 21.2545 13.9061C20.7975 17.5631 17.8085 20.395 14.1465 20.641C12.7525 20.739 11.2845 20.739 9.89349 20.641C9.47149 20.616 9.02749 20.514 8.63949 20.354L8.48548 20.2921C7.93948 20.0701 7.66547 19.959 7.34447 20.008C7.04747 20.054 6.82849 20.209 6.39349 20.519L6.32445 20.5681C6.31945 20.5711 6.31548 20.574 6.31048 20.578C5.65848 21.064 4.9505 21.27 4.0225 21.249L3.94945 21.2471L3.75853 21.241C3.82153 21.114 3.89648 20.9721 3.96048 20.8521C4.70448 19.4551 4.81351 18.2621 4.28451 17.3061C4.27451 17.2881 4.26448 17.27 4.25248 17.253C3.35748 15.91 2.86454 14.627 2.78754 13.444C2.73954 12.649 2.73954 11.8081 2.78754 11.0181C3.04254 7.16607 6.09945 4.07109 9.90345 3.81709C10.3835 3.78209 10.9145 3.76002 11.5265 3.74902H12.5195C12.9335 3.74902 13.2695 3.41302 13.2695 2.99902C13.2695 2.58502 12.9335 2.24902 12.5195 2.24902H11.5065C10.8635 2.26002 10.3044 2.28302 9.79945 2.32002C7.58645 2.46702 5.50547 3.42105 3.94046 5.00605C2.37946 6.58705 1.43846 8.68705 1.29046 10.923C1.23846 11.789 1.23846 12.667 1.29046 13.537C1.38446 14.98 1.95448 16.5 2.98548 18.054C3.29748 18.656 2.96946 19.5221 2.63646 20.1471C2.22146 20.9291 1.92249 21.4941 2.26449 22.1051L2.27054 22.116C2.61454 22.706 3.21148 22.7251 3.90248 22.7461L3.9805 22.748Z" fill="#2B353E"/> | ||||
| <path fill-rule="evenodd" clip-rule="evenodd" d="M16.0374 12.248H19.9573C21.0113 12.248 21.7364 11.681 22.1884 11.257C22.7144 10.768 22.7774 10.273 22.7374 9.944C22.6265 9.02877 21.6441 8.48097 20.9931 8.11797L20.9914 8.11704L20.9832 8.11254C20.9105 8.07232 20.8443 8.03576 20.7893 8.00298C19.0933 6.99998 16.9023 6.99998 15.2063 8.00298C15.1641 8.02733 15.1167 8.05376 15.0657 8.08222L15.0017 8.11797C14.3506 8.48098 13.3682 9.02878 13.2573 9.944C13.2183 10.273 13.2804 10.767 13.8044 11.255C14.2584 11.681 14.9834 12.248 16.0374 12.248ZM14.8283 10.159C14.8023 10.134 14.7833 10.113 14.7693 10.097H14.7704C14.9225 9.8803 15.5203 9.54694 15.7316 9.42907L15.7426 9.42298C15.8258 9.37654 15.9023 9.33385 15.9683 9.294H15.9704C17.2024 8.565 18.7943 8.56497 20.0283 9.29497C20.0941 9.33369 20.1702 9.37617 20.253 9.42238L20.2613 9.42701C20.4703 9.54301 21.0734 9.87903 21.2264 10.097C21.2124 10.114 21.1923 10.135 21.1643 10.161C20.7263 10.572 20.3653 10.748 19.9573 10.748H16.0374C15.6294 10.748 15.2693 10.572 14.8283 10.159Z" fill="#2B353E"/> | ||||
| <path d="M8.49731 15.748H15.4973C15.9113 15.748 16.2473 15.412 16.2473 14.998C16.2473 14.584 15.9113 14.248 15.4973 14.248H8.49731C8.08331 14.248 7.74731 14.584 7.74731 14.998C7.74731 15.412 8.08331 15.748 8.49731 15.748Z" fill="#2B353E"/> | ||||
| <path d="M8.49731 10.748H10.4973C10.9113 10.748 11.2473 10.412 11.2473 9.99805C11.2473 9.58405 10.9113 9.24805 10.4973 9.24805H8.49731C8.08331 9.24805 7.74731 9.58405 7.74731 9.99805C7.74731 10.412 8.08331 10.748 8.49731 10.748Z" fill="#2B353E"/> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 3.7 KiB | 
| @ -0,0 +1,5 @@ | ||||
| <svg width="10" height="13" viewBox="0 0 10 13" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||||
| <path fill-rule="evenodd" clip-rule="evenodd" d="M5 2.85449C3.79188 2.85449 2.8125 3.83387 2.8125 5.04199C2.8125 6.25011 3.79188 7.22949 5 7.22949C6.20812 7.22949 7.1875 6.25011 7.1875 5.04199C7.1875 3.83387 6.20812 2.85449 5 2.85449ZM3.6875 5.04199C3.6875 4.31712 4.27513 3.72949 5 3.72949C5.72487 3.72949 6.3125 4.31712 6.3125 5.04199C6.3125 5.76687 5.72487 6.35449 5 6.35449C4.27513 6.35449 3.6875 5.76687 3.6875 5.04199Z" fill="#ED1C2B"/> | ||||
| <path fill-rule="evenodd" clip-rule="evenodd" d="M5 0.229492C2.38798 0.229492 0.1875 2.42783 0.1875 5.09268C0.1875 7.8228 2.43772 9.64709 4.31579 10.8329L4.32334 10.8377L4.33107 10.8422C4.5346 10.9593 4.76514 11.0212 5 11.0212C5.23486 11.0212 5.4654 10.9593 5.66893 10.8422L5.67567 10.8383L5.68227 10.8342C7.56769 9.65737 9.8125 7.81358 9.8125 5.09268C9.8125 2.42783 7.61202 0.229492 5 0.229492ZM1.0625 5.09268C1.0625 2.90553 2.87676 1.10449 5 1.10449C7.12324 1.10449 8.9375 2.90553 8.9375 5.09268C8.9375 7.29808 7.10717 8.91207 5.22662 10.0871C5.15694 10.1259 5.079 10.1462 5 10.1462C4.92132 10.1462 4.84369 10.1261 4.77422 10.0876C2.89372 8.89884 1.0625 7.30546 1.0625 5.09268Z" fill="#ED1C2B"/> | ||||
| <path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 10.7295C1.73936 10.7295 1.93382 10.9217 1.93745 11.1602C1.94159 11.1712 1.96197 11.2114 2.04585 11.2775C2.16816 11.3739 2.37227 11.4798 2.66348 11.5769C3.24132 11.7695 4.06744 11.8962 5 11.8962C5.93256 11.8962 6.75868 11.7695 7.33652 11.5769C7.62773 11.4798 7.83184 11.3739 7.95415 11.2775C8.03803 11.2114 8.05841 11.1712 8.06255 11.1602C8.06618 10.9217 8.26064 10.7295 8.5 10.7295C8.74162 10.7295 8.9375 10.9254 8.9375 11.167C8.9375 11.5196 8.72273 11.7859 8.49575 11.9647C8.26385 12.1475 7.95539 12.2929 7.61322 12.407C6.92432 12.6366 6.00044 12.7712 5 12.7712C3.99956 12.7712 3.07568 12.6366 2.38678 12.407C2.04461 12.2929 1.73615 12.1475 1.50425 11.9647C1.27727 11.7859 1.0625 11.5196 1.0625 11.167C1.0625 10.9254 1.25838 10.7295 1.5 10.7295ZM8.06349 11.1572C8.06349 11.1571 8.06349 11.1572 8.06349 11.1572V11.1572Z" fill="#ED1C2B"/> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 2.1 KiB | 
| @ -0,0 +1,5 @@ | ||||
| <svg width="14" height="13" viewBox="0 0 14 13" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||||
| <path fill-rule="evenodd" clip-rule="evenodd" d="M1.47635 0.357633C1.3055 0.186779 1.02849 0.186779 0.857633 0.357633C0.686779 0.528487 0.686779 0.805497 0.857633 0.976351L2.46119 2.57991C1.74908 3.50857 1.31283 4.60696 1.31283 5.87371C1.31283 7.46181 1.98475 8.7894 2.92684 9.88512C3.86488 10.9761 5.08602 11.856 6.2293 12.5637L6.23681 12.5684L6.24451 12.5727C6.47506 12.7029 6.73552 12.7712 7.00033 12.7712C7.26514 12.7712 7.52559 12.7029 7.75614 12.5727L7.76285 12.5689L7.76943 12.5649C8.63521 12.0351 9.66148 11.3872 10.4965 10.6152L12.5243 12.643C12.6952 12.8139 12.9722 12.8139 13.143 12.643C13.3139 12.4722 13.3139 12.1952 13.143 12.0243L8.48292 7.3642C8.47847 7.35955 8.47393 7.35501 8.46931 7.35059L5.56673 4.44802C5.5623 4.44339 5.55776 4.43884 5.5531 4.43438L1.47635 0.357633ZM4.72223 4.84095L3.08613 3.20485C2.51802 3.9791 2.18783 4.86436 2.18783 5.87371C2.18783 7.19521 2.74204 8.32806 3.59032 9.31467C4.44051 10.3035 5.57042 11.1262 6.68141 11.8145C6.77877 11.868 6.88851 11.8962 7.00033 11.8962C7.11248 11.8962 7.22255 11.8678 7.32013 11.814C8.18224 11.2864 9.12483 10.6862 9.87729 9.99601L8.07636 8.19508C7.73263 8.32898 7.33404 8.39615 7.00033 8.39615C5.63112 8.39615 4.52116 7.28619 4.52116 5.91698C4.52116 5.58326 4.58833 5.18468 4.72223 4.84095ZM7.36809 7.48681L5.4305 5.54922C5.40846 5.67294 5.39616 5.79917 5.39616 5.91698C5.39616 6.80294 6.11437 7.52115 7.00033 7.52115C7.11814 7.52115 7.24437 7.50884 7.36809 7.48681Z" fill="#2E3039"/> | ||||
| <path d="M7.0004 1.10449C6.13419 1.10449 5.31049 1.34359 4.59613 1.76103C4.38751 1.88294 4.11957 1.81265 3.99766 1.60403C3.87575 1.39541 3.94605 1.12747 4.15466 1.00556C4.99638 0.513701 5.97157 0.229492 7.0004 0.229492C10.0778 0.229492 12.6879 2.77256 12.6879 5.87369C12.6879 6.94853 12.3781 7.91037 11.8817 8.76226C11.76 8.97103 11.4922 9.04165 11.2834 8.92C11.0746 8.79834 11.004 8.53049 11.1257 8.32172C11.5556 7.58384 11.8129 6.77241 11.8129 5.87369C11.8129 3.26657 9.60535 1.10449 7.0004 1.10449Z" fill="#2E3039"/> | ||||
| <path d="M7.00038 4.31283C6.92215 4.31283 6.84547 4.31839 6.77066 4.32909C6.53147 4.36331 6.30984 4.19714 6.27562 3.95795C6.24141 3.71876 6.40758 3.49712 6.64677 3.46291C6.76248 3.44636 6.88056 3.43783 7.00038 3.43783C8.36959 3.43783 9.47955 4.54779 9.47955 5.91699C9.47955 6.03681 9.47102 6.15489 9.45446 6.27061C9.42025 6.5098 9.19861 6.67596 8.95942 6.64175C8.72023 6.60754 8.55407 6.3859 8.58828 6.14671C8.59898 6.07191 8.60455 5.99523 8.60455 5.91699C8.60455 5.03103 7.88634 4.31283 7.00038 4.31283Z" fill="#2E3039"/> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 2.5 KiB | 
| @ -0,0 +1,6 @@ | ||||
| <svg width="22" height="20" viewBox="0 0 22 20" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||||
| <path d="M13.75 6C13.75 6.41421 13.4142 6.75 13 6.75L5 6.75C4.58579 6.75 4.25 6.41421 4.25 6C4.25 5.58579 4.58579 5.25 5 5.25L13 5.25C13.4142 5.25 13.75 5.58579 13.75 6Z" fill="#2B353E"/> | ||||
| <path d="M13 10.75C13.4142 10.75 13.75 10.4142 13.75 10C13.75 9.58579 13.4142 9.25 13 9.25H5C4.58579 9.25 4.25 9.58579 4.25 10C4.25 10.4142 4.58579 10.75 5 10.75H13Z" fill="#2B353E"/> | ||||
| <path d="M9.75 14C9.75 14.4142 9.41421 14.75 9 14.75H5C4.58579 14.75 4.25 14.4142 4.25 14C4.25 13.5858 4.58579 13.25 5 13.25H9C9.41421 13.25 9.75 13.5858 9.75 14Z" fill="#2B353E"/> | ||||
| <path fill-rule="evenodd" clip-rule="evenodd" d="M6.94513 0.250001H11.0549C12.4225 0.24998 13.5248 0.249964 14.3918 0.366525C15.2919 0.487541 16.0497 0.746435 16.6517 1.34835C17.2536 1.95027 17.5125 2.70814 17.6335 3.60825C17.6973 4.08322 17.7262 4.62883 17.7393 5.25L18.0494 5.25C18.7142 5.24997 19.2871 5.24993 19.7458 5.31161C20.2375 5.37771 20.7087 5.52677 21.091 5.90901C21.4732 6.29126 21.6223 6.76252 21.6884 7.25416C21.7501 7.7129 21.75 8.28575 21.75 8.9506L21.75 17C21.75 18.5188 20.5188 19.75 19 19.75C18.9989 19.75 18.9978 19.75 18.9967 19.75H6.94513C5.57754 19.75 4.47522 19.75 3.60825 19.6335C2.70814 19.5125 1.95027 19.2536 1.34835 18.6517C0.746435 18.0497 0.487541 17.2919 0.366525 16.3918C0.249964 15.5248 0.24998 14.4225 0.250001 13.0549V6.94513C0.24998 5.57754 0.249964 4.47521 0.366525 3.60825C0.487541 2.70814 0.746435 1.95027 1.34835 1.34835C1.95027 0.746435 2.70814 0.487541 3.60825 0.366525C4.47521 0.249964 5.57754 0.24998 6.94513 0.250001ZM18.9978 18.25C18.9985 18.25 18.9993 18.25 19 18.25C19.6904 18.25 20.25 17.6904 20.25 17V9C20.25 8.2717 20.2484 7.80091 20.2018 7.45403C20.158 7.12873 20.0874 7.02677 20.0303 6.96967C19.9732 6.91258 19.8713 6.84197 19.546 6.79823C19.1991 6.7516 18.7283 6.75 18 6.75H17.75V6.81344C17.75 6.85706 17.75 6.90096 17.75 6.94513V13C17.75 13.0006 17.75 13.0011 17.75 13.0017V17C17.75 17.6896 18.3085 18.2488 18.9978 18.25ZM16.25 17C16.25 17.4501 16.3581 17.875 16.5499 18.25H7C5.56459 18.25 4.56347 18.2484 3.80812 18.1469C3.07435 18.0482 2.68577 17.8678 2.40901 17.591C2.13225 17.3142 1.9518 16.9257 1.85315 16.1919C1.75159 15.4365 1.75 14.4354 1.75 13V7C1.75 5.56459 1.75159 4.56347 1.85315 3.80812C1.9518 3.07435 2.13225 2.68577 2.40901 2.40901C2.68577 2.13225 3.07435 1.9518 3.80812 1.85315C4.56347 1.75159 5.56459 1.75 7 1.75H11C12.4354 1.75 13.4365 1.75159 14.1919 1.85315C14.9257 1.9518 15.3142 2.13225 15.591 2.40901C15.8678 2.68577 16.0482 3.07435 16.1469 3.80812C16.2467 4.5505 16.2499 5.53028 16.25 6.92645C16.25 6.95084 16.25 6.97536 16.25 7L16.25 17Z" fill="#2B353E"/> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 2.6 KiB | 
| @ -0,0 +1,207 @@ | ||||
| import 'dart:math'; | ||||
| 
 | ||||
| import 'package:hmg_patient_app_new/core/cache_consts.dart' show CacheConst; | ||||
| import 'package:hmg_patient_app_new/core/utils/utils.dart' show Utils; | ||||
| import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.dart' show RegionList, PatientDoctorAppointmentList, DoctorList, PatientDoctorAppointmentListByRegion; | ||||
| import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart' show HospitalsModel; | ||||
| 
 | ||||
| class DoctorMapper{ | ||||
|   static Future<RegionList> getMappedDoctor(List<DoctorList> doctorList, | ||||
|       {bool isArabic = false}) async { | ||||
|     RegionList regionList = RegionList(); | ||||
|     final lat = await Utils.getNumFromPrefs(CacheConst.userLat); | ||||
|     final long = await Utils.getNumFromPrefs(CacheConst.userLat); | ||||
| 
 | ||||
|     for (var element in doctorList) { | ||||
|       String? region = element.getRegionName(isArabic); | ||||
|       if (region == null) continue; | ||||
| 
 | ||||
|       var regionDoctorList = regionList.registeredDoctorMap?.putIfAbsent(region, () => PatientDoctorAppointmentListByRegion()); | ||||
| 
 | ||||
|       List<PatientDoctorAppointmentList>? targetList = element.isHMC == true | ||||
|           ? regionDoctorList?.hmcDoctorList | ||||
|           : regionDoctorList?.hmgDoctorList; | ||||
| 
 | ||||
|       var doctorByHospital = targetList | ||||
|               ?.where((clinic) => | ||||
|                   clinic.filterName == | ||||
|                   element.getProjectCompleteNameWithLocale(isArabic: isArabic)) | ||||
|               .toList() ?? | ||||
|           []; | ||||
| 
 | ||||
|       if (doctorByHospital.isNotEmpty) { | ||||
|         doctorByHospital.first.patientDoctorAppointmentList?.add(element); | ||||
|       } else { | ||||
|         var newAppointment = PatientDoctorAppointmentList( | ||||
|           filterName: | ||||
|               element.getProjectCompleteNameWithLocale(isArabic: isArabic), | ||||
|           distanceInKMs: element.projectDistanceInKiloMeters.toString(), | ||||
|           projectTopName: element.projectTopName, | ||||
|           projectBottomName: element.projectBottomName, | ||||
|           patientDoctorAppointment: element, | ||||
|           isHMC: element.isHMC | ||||
|         ); | ||||
|         if(element.projectDistanceInKiloMeters!= null ){ | ||||
|           if(regionDoctorList!.distance>element.projectDistanceInKiloMeters){ | ||||
|             regionDoctorList.distance = element.projectDistanceInKiloMeters; | ||||
|           } | ||||
|           if (element.isHMC == true && | ||||
|               element.projectDistanceInKiloMeters < | ||||
|                   regionDoctorList.hmcDistance) { | ||||
|             regionDoctorList.hmcDistance = element.projectDistanceInKiloMeters; | ||||
|           } else if (element.projectDistanceInKiloMeters < | ||||
|               regionDoctorList.hmgDistance) { | ||||
|             regionDoctorList.hmgDistance = element.projectDistanceInKiloMeters; | ||||
|           } | ||||
|         }else | ||||
|         if (lat != 0&& | ||||
|             long != 0 && element.latitude != null && element.longitude != null) { | ||||
| 
 | ||||
| 
 | ||||
|           double distance =  calculateDistance(lat.toDouble(), long.toDouble(), double.parse(element.latitude!), double.parse(element.longitude!)); | ||||
|           if(distance<0){ | ||||
|             distance *= -1; | ||||
|           } | ||||
|           if(regionDoctorList!.distance>distance){ | ||||
|             regionDoctorList.distance = distance; | ||||
|           } | ||||
|           if (element.isHMC == true && | ||||
|               element.projectDistanceInKiloMeters < | ||||
|                   regionDoctorList.hmcDistance) { | ||||
|             regionDoctorList.hmcDistance = element.projectDistanceInKiloMeters; | ||||
|           } else if (element.projectDistanceInKiloMeters < | ||||
|               regionDoctorList.hmgDistance) { | ||||
|             regionDoctorList.hmgDistance = element.projectDistanceInKiloMeters; | ||||
|           } | ||||
|         } | ||||
|         targetList?.add(newAppointment); | ||||
|       } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|       regionDoctorList?.hmcSize = regionDoctorList.hmcDoctorList?.length ?? 0; | ||||
|       regionDoctorList?.hmgSize = regionDoctorList.hmgDoctorList?.length ?? 0; | ||||
| 
 | ||||
|       regionList.registeredDoctorMap?[region] = regionDoctorList; | ||||
|     } | ||||
| 
 | ||||
|     return regionList; | ||||
|   } | ||||
|   static double calculateDistance(double lat1, double lon1, double lat2, double lon2) { | ||||
|     var pi = 3.142; | ||||
|     const double R = 6371; | ||||
|     double dLat = (lat2 - lat1) * pi / 180; | ||||
|     double dLon = (lon2 - lon1) * pi / 180; | ||||
|     double a = sin(dLat / 2) * sin(dLat / 2) + | ||||
|         cos(lat1 * pi / 180) * cos(lat2 * pi / 180) * sin(dLon / 2) * sin(dLon / 2); | ||||
|     double c = 2 * atan2(sqrt(a), sqrt(1 - a)); | ||||
|     return R * c; | ||||
|   } | ||||
| 
 | ||||
|   static Future<RegionList> sortList(bool isGPSEnabled, RegionList unsorted, )  async { | ||||
|     if(isGPSEnabled){ | ||||
|       if(unsorted.registeredDoctorMap == null) return unsorted; | ||||
|       var sortedMap = Map.fromEntries( | ||||
|         unsorted.registeredDoctorMap!.entries.toList() | ||||
|           ..sort((a, b) => a.value!.distance.compareTo(b.value!.distance)), | ||||
|       ); | ||||
| 
 | ||||
|       unsorted.registeredDoctorMap = sortedMap; | ||||
|       return unsorted; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     List<String>? keys = unsorted.registeredDoctorMap?.keys.toList(); | ||||
|     keys?.sort(); | ||||
| 
 | ||||
|     if (keys == null) return unsorted; | ||||
|     Map<String, PatientDoctorAppointmentListByRegion> sortedMap = {}; | ||||
|     for (var key in keys) { | ||||
|       sortedMap[key] = unsorted.registeredDoctorMap![key]!; | ||||
|     } | ||||
|     unsorted.registeredDoctorMap = sortedMap; | ||||
|     return unsorted; | ||||
|   } | ||||
| 
 | ||||
|   static Future<RegionList> getMappedHospitals( | ||||
|     List<HospitalsModel> hospitalList, { | ||||
|     bool isArabic = false, | ||||
|   }) async { | ||||
|     final regionList = RegionList(); | ||||
|     final lat = await Utils.getNumFromPrefs(CacheConst.userLat); | ||||
|     final long = await Utils.getNumFromPrefs(CacheConst.userLat); | ||||
|     for (final hospital in hospitalList) { | ||||
|       final region = hospital.getRegionName(isArabic); | ||||
|       if (region == null) continue; | ||||
| 
 | ||||
|       final regionData = regionList.registeredDoctorMap?.putIfAbsent( | ||||
|         region, | ||||
|         () => PatientDoctorAppointmentListByRegion(), | ||||
|       ); | ||||
| 
 | ||||
|       List<PatientDoctorAppointmentList>? targetList = hospital.isHMC == true | ||||
|           ? regionData?.hmcDoctorList | ||||
|           : regionData?.hmgDoctorList; | ||||
| 
 | ||||
|       List<PatientDoctorAppointmentList> existingEntry = targetList | ||||
|               ?.where( | ||||
|                 (entry) => entry.filterName == hospital.getName(isArabic), | ||||
|               ) | ||||
|               .toList() ?? | ||||
|           []; | ||||
| 
 | ||||
|       if (existingEntry.isNotEmpty) { | ||||
|         existingEntry.first.hospitalList.add(hospital); | ||||
|       } else { | ||||
|         final newEntry = PatientDoctorAppointmentList( | ||||
|             filterName: hospital.name, | ||||
|             distanceInKMs: hospital.distanceInKilometers?.toString(), | ||||
|             projectTopName: hospital.name, | ||||
|             projectBottomName: hospital.name, | ||||
|             model: hospital, | ||||
|         isHMC: hospital.isHMC); | ||||
| 
 | ||||
|         final distance = hospital.distanceInKilometers; | ||||
| 
 | ||||
|         if (distance != null) { | ||||
|           if (regionData!.distance > distance) { | ||||
|             regionData.distance = distance; | ||||
|           } | ||||
|           if (hospital.isHMC == true && distance < regionData.hmcDistance) { | ||||
|             regionData.hmcDistance = distance; | ||||
|           } else if (distance < regionData.hmgDistance) { | ||||
|             regionData.hmgDistance = distance; | ||||
|           } | ||||
|         } else if ( lat != 0&& | ||||
|             long != 0 && | ||||
|             hospital.latitude != null && | ||||
|             hospital.longitude != null) { | ||||
|           double calculatedDistance = calculateDistance( | ||||
|             lat.toDouble(), | ||||
|             long.toDouble(), | ||||
|             double.parse(hospital.latitude!), | ||||
|             double.parse(hospital.longitude!), | ||||
|           ).abs(); | ||||
| 
 | ||||
|           if (regionData!.distance > calculatedDistance) { | ||||
|             regionData.distance = calculatedDistance; | ||||
|           } | ||||
|           if (hospital.isHMC == true && | ||||
|               calculatedDistance < regionData.hmcDistance) { | ||||
|             regionData.hmcDistance = calculatedDistance; | ||||
|           } else if (calculatedDistance < regionData.hmgDistance) { | ||||
|             regionData.hmgDistance = calculatedDistance; | ||||
|           } | ||||
|         } | ||||
|         targetList?.add(newEntry); | ||||
|       } | ||||
| 
 | ||||
|       regionData?.hmcSize = regionData.hmcDoctorList?.length ?? 0; | ||||
|       regionData?.hmgSize = regionData.hmgDoctorList?.length ?? 0; | ||||
|       regionList.registeredDoctorMap?[region] = regionData; | ||||
|     } | ||||
| 
 | ||||
|     return regionList; | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,66 @@ | ||||
| import 'package:flutter/foundation.dart' show ChangeNotifier; | ||||
| 
 | ||||
| enum AppointmentViaRegionState { | ||||
|   REGION_SELECTION, | ||||
|   TYPE_SELECTION, | ||||
|   HOSPITAL_SELECTION, | ||||
|   CLINIC_SELECTION, | ||||
|   DOCTOR_SELECTION | ||||
| } | ||||
| 
 | ||||
| class AppointmentViaRegionViewmodel extends ChangeNotifier { | ||||
|   String? selectedRegionId; | ||||
|   String? selectedFacilityType; | ||||
|   AppointmentViaRegionState bottomSheetState = | ||||
|       AppointmentViaRegionState.REGION_SELECTION; | ||||
| 
 | ||||
|   void setSelectedRegionId(String? regionId) { | ||||
|     selectedRegionId = regionId; | ||||
|     notifyListeners(); | ||||
|   } | ||||
| 
 | ||||
|   void setFacility(String? facility) { | ||||
|     selectedFacilityType = facility; | ||||
|     notifyListeners(); | ||||
|   } | ||||
| 
 | ||||
|   void setBottomSheetState(AppointmentViaRegionState state) { | ||||
|     bottomSheetState = state; | ||||
|     notifyListeners(); | ||||
|   } | ||||
| 
 | ||||
|   void handleBackPress() { | ||||
|     switch (bottomSheetState) { | ||||
|       case AppointmentViaRegionState.REGION_SELECTION: | ||||
|         // Do nothing or exit the bottom sheet | ||||
|         break; | ||||
|       case AppointmentViaRegionState.TYPE_SELECTION: | ||||
|         setBottomSheetState(AppointmentViaRegionState.REGION_SELECTION); | ||||
|         setSelectedRegionId(null); | ||||
|         break; | ||||
|       case AppointmentViaRegionState.HOSPITAL_SELECTION: | ||||
|         setBottomSheetState(AppointmentViaRegionState.TYPE_SELECTION); | ||||
|         break; | ||||
| 
 | ||||
|       // case AppointmentViaRegionState.HOSPITAL_SELECTION: | ||||
|       // case AppointmentViaRegionState.CLINIC_SELECTION: | ||||
|       //   setBottomSheetState(AppointmentViaRegionState.TYPE_SELECTION); | ||||
|       //   setFacility(null); | ||||
|       //   break; | ||||
|       // case AppointmentViaRegionState.DOCTOR_SELECTION: | ||||
|       //   if (selectedFacilityType == 'Hospital') { | ||||
|       //     setBottomSheetState(AppointmentViaRegionState.HOSPITAL_SELECTION); | ||||
|       //   } else if (selectedFacilityType == 'Medical Center') { | ||||
|       //     setBottomSheetState(AppointmentViaRegionState.CLINIC_SELECTION); | ||||
|       //   } | ||||
|       //   break; | ||||
|       default: | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   void flush() { | ||||
|     setSelectedRegionId(null); | ||||
|     setFacility(null); | ||||
|     setBottomSheetState(AppointmentViaRegionState.REGION_SELECTION); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,8 @@ | ||||
| enum FacilitySelection{ | ||||
| ALL('ALL'), | ||||
| HMG('hmg'), | ||||
| HMC('hmc'); | ||||
| 
 | ||||
| final String value; | ||||
| const FacilitySelection(this.value); | ||||
| } | ||||
| @ -0,0 +1,274 @@ | ||||
| 
 | ||||
| import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart' show HospitalsModel; | ||||
| 
 | ||||
| class DoctorList { | ||||
|   int? clinicID; | ||||
|   dynamic appointmentNo; | ||||
|   String? clinicName; | ||||
|   String? doctorTitle; | ||||
|   num? iD; | ||||
|   String? name; | ||||
|   int? projectID; | ||||
|   String? projectName; | ||||
|   int? actualDoctorRate; | ||||
|   num? clinicRoomNo; | ||||
|   dynamic date; | ||||
|   dynamic appointmentDate; | ||||
|   dynamic dayName; | ||||
|   int? doctorID; | ||||
|   String? doctorImageURL; | ||||
|   dynamic doctorProfile; | ||||
|   dynamic doctorProfileInfo; | ||||
|   int? doctorRate; | ||||
|   num? gender; | ||||
|   String? genderDescription; | ||||
|   bool? isAppointmentAllowed; | ||||
|   bool? isDoctorAllowVedioCall; | ||||
|   bool? isDoctorDummy; | ||||
|   bool? isLiveCare; | ||||
|   bool? isLiveCareClinic; | ||||
|   bool? isDoctorHasPrePostImages; | ||||
|   String? latitude; | ||||
|   String? longitude; | ||||
|   String? nationalityFlagURL; | ||||
|   String? nationalityID; | ||||
|   String? nationalityName; | ||||
|   dynamic nearestFreeSlot; | ||||
|   int? noOfPatientsRate; | ||||
|   num? originalClinicID; | ||||
|   num? personRate; | ||||
|   dynamic projectDistanceInKiloMeters; | ||||
|   String? qR; | ||||
|   dynamic qRString; | ||||
|   num? rateNumber; | ||||
|   dynamic serviceID; | ||||
|   String? setupID; | ||||
|   List<String>? speciality; | ||||
|   List<String>? specialityN; | ||||
|   dynamic workingHours; | ||||
|   dynamic decimalDoctorRate; | ||||
|   String? projectBottomName; | ||||
|   String? projectTopName; | ||||
|   bool? isHMC; | ||||
|   String? region; | ||||
|   String? regionArabic; | ||||
|   String? regionEnglish; | ||||
|   String? regionID; | ||||
| 
 | ||||
|   DoctorList( | ||||
|       {this.clinicID, | ||||
|       this.appointmentNo, | ||||
|       this.clinicName, | ||||
|       this.doctorTitle, | ||||
|       this.iD, | ||||
|       this.name, | ||||
|       this.projectID, | ||||
|       this.projectName, | ||||
|       this.actualDoctorRate, | ||||
|       this.clinicRoomNo, | ||||
|       this.date, | ||||
|       this.appointmentDate, | ||||
|       this.dayName, | ||||
|       this.doctorID, | ||||
|       this.doctorImageURL, | ||||
|       this.doctorProfile, | ||||
|       this.doctorProfileInfo, | ||||
|       this.doctorRate, | ||||
|       this.gender, | ||||
|       this.genderDescription, | ||||
|       this.isAppointmentAllowed, | ||||
|       this.isDoctorAllowVedioCall, | ||||
|       this.isDoctorDummy, | ||||
|       this.isLiveCare, | ||||
|       this.isLiveCareClinic, | ||||
|       this.isDoctorHasPrePostImages, | ||||
|       this.latitude, | ||||
|       this.longitude, | ||||
|       this.nationalityFlagURL, | ||||
|       this.nationalityID, | ||||
|       this.nationalityName, | ||||
|       this.nearestFreeSlot, | ||||
|       this.noOfPatientsRate, | ||||
|       this.originalClinicID, | ||||
|       this.personRate, | ||||
|       this.projectDistanceInKiloMeters, | ||||
|       this.qR, | ||||
|       this.qRString, | ||||
|       this.rateNumber, | ||||
|       this.serviceID, | ||||
|       this.setupID, | ||||
|       this.speciality, | ||||
|       this.specialityN, | ||||
|       this.workingHours, | ||||
|       this.decimalDoctorRate, | ||||
|       this.projectBottomName, | ||||
|       this.projectTopName, | ||||
|       this.isHMC, | ||||
|       this.region, | ||||
|     this.regionArabic, | ||||
|     this.regionEnglish, | ||||
|     this.regionID, | ||||
|       }); | ||||
| 
 | ||||
|   DoctorList.fromJson( | ||||
|     Map<String, dynamic> json, | ||||
|   ) { | ||||
|     clinicID = json['ClinicID']; | ||||
|     appointmentNo = json['AppointmentNo']; | ||||
|     clinicName = json['ClinicName']; | ||||
|     doctorTitle = json['DoctorTitle']; | ||||
|     iD = json['ID']; | ||||
|     name = json['DoctorName'] ?? json['Name']; | ||||
|     projectID = json['ProjectID']; | ||||
|     projectName = json['ProjectName']; | ||||
|     actualDoctorRate = json['ActualDoctorRate']; | ||||
|     clinicRoomNo = json['ClinicRoomNo']; | ||||
|     date = json['Date']; | ||||
|     appointmentDate = json['AppointmentDate']; | ||||
|     dayName = json['DayName']; | ||||
|     doctorID = json['DoctorID']; | ||||
|     doctorImageURL = json['DoctorImageURL']; | ||||
|     doctorProfile = json['DoctorProfile']; | ||||
|     doctorProfileInfo = json['DoctorProfileInfo']; | ||||
|     doctorRate = json['DoctorRate']; | ||||
|     gender = json['Gender']; | ||||
|     genderDescription = json['GenderDescription']; | ||||
|     isAppointmentAllowed = json['IsAppointmentAllowed']; | ||||
|     isDoctorAllowVedioCall = json['IsDoctorAllowVedioCall']; | ||||
|     isDoctorDummy = json['IsDoctorDummy']; | ||||
|     isLiveCare = json['IsLiveCare']; | ||||
|     isLiveCareClinic = json['IsLiveCareClinic']; | ||||
|     isDoctorHasPrePostImages = json['IsDoctorHasPrePostImages']; | ||||
|     latitude = json['Latitude']; | ||||
|     longitude = json['Longitude']; | ||||
|     nationalityFlagURL = json['NationalityFlagURL']; | ||||
|     nationalityID = json['NationalityID']; | ||||
|     nationalityName = json['NationalityName']; | ||||
|     nearestFreeSlot = json['NearestFreeSlot']; | ||||
|     noOfPatientsRate = json['NoOfPatientsRate']; | ||||
|     originalClinicID = json['OriginalClinicID']; | ||||
|     personRate = json['PersonRate']; | ||||
|     projectDistanceInKiloMeters = json['ProjectDistanceInKiloMeters']; | ||||
|     qR = json['QR']; | ||||
|     qRString = json['QRString']; | ||||
|     rateNumber = json['RateNumber']; | ||||
|     serviceID = json['ServiceID']; | ||||
|     setupID = json['SetupID']; | ||||
|     if (json.containsKey('Speciality') && json['Speciality'] != null) speciality = json['Speciality'].cast<String>(); | ||||
|     if (json.containsKey('SpecialityN') && json['SpecialityN'] != null) specialityN = json['SpecialityN'].cast<String>(); | ||||
|     workingHours = json['WorkingHours']; | ||||
|     decimalDoctorRate = json['DecimalDoctorRate']; | ||||
|     projectBottomName = json['ProjectNameBottom']; | ||||
|     projectTopName = json['ProjectNameTop']; | ||||
|     this.isHMC = json["IsHMC"]; | ||||
|     this.regionArabic = json['RegionNameN']; | ||||
|     this.regionEnglish = json['RegionName']; | ||||
|   } | ||||
| 
 | ||||
|   String? getRegionName(bool isArabic) { | ||||
|     if (isArabic) { | ||||
|       return regionArabic; | ||||
|     } | ||||
|     return regionEnglish; | ||||
|   } | ||||
| 
 | ||||
|   Map<String, dynamic> toJson() { | ||||
|     final Map<String, dynamic> data = new Map<String, dynamic>(); | ||||
|     data['ClinicID'] = this.clinicID; | ||||
|     data['AppointmentNo'] = this.appointmentNo; | ||||
|     data['ClinicName'] = this.clinicName; | ||||
|     data['DoctorTitle'] = this.doctorTitle; | ||||
|     data['ID'] = this.iD; | ||||
|     data['Name'] = this.name; | ||||
|     data['ProjectID'] = this.projectID; | ||||
|     data['ProjectName'] = this.projectName; | ||||
|     data['ActualDoctorRate'] = this.actualDoctorRate; | ||||
|     data['ClinicRoomNo'] = this.clinicRoomNo; | ||||
|     data['Date'] = this.date; | ||||
|     data['DayName'] = this.dayName; | ||||
|     data['DoctorID'] = this.doctorID; | ||||
|     data['DoctorImageURL'] = this.doctorImageURL; | ||||
|     data['DoctorProfile'] = this.doctorProfile; | ||||
|     data['DoctorProfileInfo'] = this.doctorProfileInfo; | ||||
|     data['DoctorRate'] = this.doctorRate; | ||||
|     data['Gender'] = this.gender; | ||||
|     data['GenderDescription'] = this.genderDescription; | ||||
|     data['IsAppointmentAllowed'] = this.isAppointmentAllowed; | ||||
|     data['IsDoctorAllowVedioCall'] = this.isDoctorAllowVedioCall; | ||||
|     data['IsDoctorDummy'] = this.isDoctorDummy; | ||||
|     data['IsLiveCare'] = this.isLiveCare; | ||||
|     data['IsLiveCareClinic'] = this.isLiveCareClinic; | ||||
|     data['IsDoctorHasPrePostImages'] = this.isDoctorHasPrePostImages; | ||||
|     data['Latitude'] = this.latitude; | ||||
|     data['Longitude'] = this.longitude; | ||||
|     data['NationalityFlagURL'] = this.nationalityFlagURL; | ||||
|     data['NationalityID'] = this.nationalityID; | ||||
|     data['NationalityName'] = this.nationalityName; | ||||
|     data['NearestFreeSlot'] = this.nearestFreeSlot; | ||||
|     data['NoOfPatientsRate'] = this.noOfPatientsRate; | ||||
|     data['OriginalClinicID'] = this.originalClinicID; | ||||
|     data['PersonRate'] = this.personRate; | ||||
|     data['ProjectDistanceInKiloMeters'] = this.projectDistanceInKiloMeters; | ||||
|     data['QR'] = this.qR; | ||||
|     data['QRString'] = this.qRString; | ||||
|     data['RateNumber'] = this.rateNumber; | ||||
|     data['ServiceID'] = this.serviceID; | ||||
|     data['SetupID'] = this.setupID; | ||||
|     data['Speciality'] = this.speciality; | ||||
|     data['SpecialityN'] = this.specialityN; | ||||
|     data['WorkingHours'] = this.workingHours; | ||||
|     data['DecimalDoctorRate'] = this.decimalDoctorRate; | ||||
|     return data; | ||||
|   } | ||||
| 
 | ||||
|   String getProjectCompleteName(){ | ||||
|     return "${this.projectTopName} ${this.projectBottomName}"; | ||||
|   } | ||||
| 
 | ||||
|   String getProjectCompleteNameWithLocale({bool isArabic = false}) { | ||||
|     if (isArabic) { | ||||
|       return "${this.projectBottomName} ${this.projectTopName}"; | ||||
|     } | ||||
|     return "${this.projectTopName} ${this.projectBottomName}"; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class PatientDoctorAppointmentList { | ||||
|   String? filterName = ""; | ||||
|   String? distanceInKMs = ""; | ||||
|   List<DoctorList>? patientDoctorAppointmentList = []; | ||||
|   String? projectTopName = ""; | ||||
|   String? projectBottomName = ""; | ||||
|   bool? isHMC; | ||||
|   List<HospitalsModel> hospitalList = []; | ||||
| 
 | ||||
|   PatientDoctorAppointmentList( | ||||
|       {this.filterName, | ||||
|       this.distanceInKMs, | ||||
|       this.projectTopName, | ||||
|       this.projectBottomName, | ||||
|       DoctorList? patientDoctorAppointment, | ||||
|       HospitalsModel? model, | ||||
|       this.isHMC = false}) { | ||||
|     if (model != null) { | ||||
|       hospitalList.add(model); | ||||
|     } | ||||
|     if (patientDoctorAppointment != null) { | ||||
|       patientDoctorAppointmentList!.add(patientDoctorAppointment!); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class PatientDoctorAppointmentListByRegion { | ||||
|   List<PatientDoctorAppointmentList>? hmgDoctorList = []; | ||||
|   List<PatientDoctorAppointmentList>? hmcDoctorList = []; | ||||
|   int hmcSize = 0; | ||||
|   int hmgSize = 0; | ||||
|   num distance = double.infinity; | ||||
|   num hmgDistance = double.infinity; | ||||
|   num hmcDistance = double.infinity; | ||||
| } | ||||
| 
 | ||||
| class RegionList { | ||||
|   Map<String, PatientDoctorAppointmentListByRegion?>? registeredDoctorMap = {}; | ||||
| } | ||||
| @ -0,0 +1,104 @@ | ||||
| class HospitalsModel { | ||||
|   String? desciption; | ||||
|   dynamic desciptionN; | ||||
|   dynamic iD; | ||||
|   String? legalName; | ||||
|   String? legalNameN; | ||||
|   String? name; | ||||
|   dynamic nameN; | ||||
|   String? phoneNumber; | ||||
|   String? setupID; | ||||
|   dynamic distanceInKilometers; | ||||
|   bool? isActive; | ||||
|   String? latitude; | ||||
|   String? longitude; | ||||
|   dynamic mainProjectID; | ||||
|   bool? projectOutSA; | ||||
|   bool? usingInDoctorApp; | ||||
|   bool? isHMC; | ||||
|   String? region; | ||||
|   String? regionArabic; | ||||
|   String? regionEnglish; | ||||
|   String? regionID; | ||||
| 
 | ||||
|   HospitalsModel({ | ||||
|     this.desciption, | ||||
|     this.desciptionN, | ||||
|     this.iD, | ||||
|     this.legalName, | ||||
|     this.legalNameN, | ||||
|     this.name, | ||||
|     this.nameN, | ||||
|     this.phoneNumber, | ||||
|     this.setupID, | ||||
|     this.distanceInKilometers, | ||||
|     this.isActive, | ||||
|     this.latitude, | ||||
|     this.longitude, | ||||
|     this.mainProjectID, | ||||
|     this.projectOutSA, | ||||
|     this.usingInDoctorApp, | ||||
|     this.isHMC, | ||||
|     this.region, | ||||
|     this.regionArabic, | ||||
|     this.regionEnglish, | ||||
|     this.regionID, | ||||
|   }); | ||||
| 
 | ||||
|   HospitalsModel.fromJson(Map<String, dynamic> json) { | ||||
|     desciption = json['Desciption']; | ||||
|     desciptionN = json['DesciptionN']; | ||||
|     iD = json['ID']; | ||||
|     legalName = json['LegalName']; | ||||
|     legalNameN = json['LegalNameN']; | ||||
|     name = json['Name']; | ||||
|     nameN = json['NameN']; | ||||
|     phoneNumber = json['PhoneNumber']; | ||||
|     setupID = json['SetupID']; | ||||
|     distanceInKilometers = json['DistanceInKilometers']; | ||||
|     isActive = json['IsActive']; | ||||
|     latitude = json['Latitude']; | ||||
|     longitude = json['Longitude']; | ||||
|     mainProjectID = json['MainProjectID']; | ||||
|     projectOutSA = json['ProjectOutSA']; | ||||
|     usingInDoctorApp = json['UsingInDoctorApp']; | ||||
|     this.isHMC = json["IsHMC"]; | ||||
|     this.regionArabic = json['RegionNameN']; | ||||
|     this.regionEnglish = json['RegionName']; | ||||
|   } | ||||
| 
 | ||||
|   String? getRegionName(bool isArabic) { | ||||
|     if (isArabic) { | ||||
|       return regionArabic; | ||||
|     } | ||||
|     return regionEnglish; | ||||
|   } | ||||
| 
 | ||||
|   String? getName(bool isArabic) { | ||||
|     if (isArabic) { | ||||
|       return "$nameN"; | ||||
|     } | ||||
|     return name; | ||||
|   } | ||||
| 
 | ||||
|   Map<String, dynamic> toJson() { | ||||
|     final Map<String, dynamic> data = new Map<String, dynamic>(); | ||||
|     data['Desciption'] = this.desciption; | ||||
|     data['DesciptionN'] = this.desciptionN; | ||||
|     data['ID'] = this.iD; | ||||
|     data['LegalName'] = this.legalName; | ||||
|     data['LegalNameN'] = this.legalNameN; | ||||
|     data['Name'] = this.name; | ||||
|     data['NameN'] = this.nameN; | ||||
|     data['PhoneNumber'] = this.phoneNumber; | ||||
|     data['SetupID'] = this.setupID; | ||||
|     data['DistanceInKilometers'] = this.distanceInKilometers; | ||||
|     data['IsActive'] = this.isActive; | ||||
|     data['Latitude'] = this.latitude; | ||||
|     data['Longitude'] = this.longitude; | ||||
|     data['MainProjectID'] = this.mainProjectID; | ||||
|     data['ProjectOutSA'] = this.projectOutSA; | ||||
|     data['UsingInDoctorApp'] = this.usingInDoctorApp; | ||||
|     return data; | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,88 @@ | ||||
| import 'package:flutter/material.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'; | ||||
| 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/theme/colors.dart' show AppColors; | ||||
| import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; | ||||
| import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; | ||||
| 
 | ||||
| class FacilitySelectionItem extends StatelessWidget { | ||||
|   final String svgPath; | ||||
|   final String title; | ||||
|   final String subTitle; | ||||
| 
 | ||||
|   const FacilitySelectionItem( | ||||
|       {super.key, | ||||
|       required this.svgPath, | ||||
|       required this.subTitle, | ||||
|       required this.title}); | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Container( | ||||
|       decoration: RoundedRectangleBorder().toSmoothCornerDecoration( | ||||
|         color: AppColors.whiteColor, | ||||
|         borderRadius: 20.h, | ||||
|         hasShadow: false, | ||||
|       ), | ||||
|       child: Column( | ||||
|         mainAxisAlignment: MainAxisAlignment.start, | ||||
|         crossAxisAlignment: CrossAxisAlignment.start, | ||||
|         children: [ | ||||
|       Utils.buildSvgWithAssets( | ||||
|       icon:  svgPath, | ||||
|         width: 32, | ||||
|         height: 32, | ||||
|         fit: BoxFit.contain, | ||||
|       ), | ||||
|           SizedBox(height: 16,), | ||||
|           Row( | ||||
|             mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|             children: [ | ||||
|               info, | ||||
|               Utils.buildSvgWithAssets( | ||||
|                 icon: AppAssets.forward_arrow_icon, | ||||
|                 iconColor: AppColors.blackColor, | ||||
|                 width: 18, | ||||
|                 height: 13, | ||||
|                 fit: BoxFit.contain, | ||||
|               ), | ||||
|             ], | ||||
|           ) | ||||
|         ], | ||||
|       ).paddingAll(16.h), | ||||
|     ); | ||||
|   } | ||||
|    | ||||
| 
 | ||||
|  Widget get info => Column( | ||||
|         mainAxisAlignment: MainAxisAlignment.start, | ||||
|         crossAxisAlignment: CrossAxisAlignment.start, | ||||
|         children: [ | ||||
|           Align( | ||||
|             alignment: Alignment.centerLeft, | ||||
|             child: Text( | ||||
|               title, | ||||
|               style: TextStyle( | ||||
|                 fontSize: 16.h, | ||||
|                 fontWeight: FontWeight.w600, | ||||
|                 color: AppColors.blackColor, | ||||
|               ), | ||||
|             ), | ||||
|           ), | ||||
|           Align( | ||||
|             alignment: Alignment.centerLeft, | ||||
|             child: Text( | ||||
|               subTitle, | ||||
|               style: TextStyle( | ||||
|                 fontSize: 12.h, | ||||
|                 fontWeight: FontWeight.w500, | ||||
|                 color: AppColors.greyTextColor, | ||||
|               ), | ||||
|             ), | ||||
|           ), | ||||
|         ], | ||||
|       ); | ||||
| } | ||||
| @ -0,0 +1,79 @@ | ||||
| import 'package:easy_localization/easy_localization.dart' | ||||
|     show tr, StringTranslateExtension; | ||||
| import 'package:flutter/cupertino.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/extensions/string_extensions.dart'; | ||||
| import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; | ||||
| import 'package:hmg_patient_app_new/features/my_appointments/appointment_via_region_viewmodel.dart'; | ||||
| import 'package:hmg_patient_app_new/features/my_appointments/models/facility_selection.dart'; | ||||
| import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart' | ||||
|     show MyAppointmentsViewModel; | ||||
| import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; | ||||
| import 'package:hmg_patient_app_new/presentation/appointments/widgets/faculity_selection/facility_selection_item.dart'; | ||||
| import 'package:hmg_patient_app_new/theme/colors.dart'; | ||||
| import 'package:provider/provider.dart' show Provider; | ||||
| 
 | ||||
| class FacilityTypeSelectionWidget extends StatelessWidget { | ||||
|   late MyAppointmentsViewModel myAppointmentsViewModel; | ||||
|   late AppointmentViaRegionViewmodel regionalViewModel; | ||||
|   final String selectedRegion; | ||||
| 
 | ||||
|   FacilityTypeSelectionWidget({super.key, required this.selectedRegion}); | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     myAppointmentsViewModel = Provider.of<MyAppointmentsViewModel>(context); | ||||
|     regionalViewModel = Provider.of<AppointmentViaRegionViewmodel>(context); | ||||
|     return Column( | ||||
|       crossAxisAlignment: CrossAxisAlignment.start, | ||||
|       children: [ | ||||
|         Text( | ||||
|           LocaleKeys.selectFacility.tr(), | ||||
|           style: TextStyle( | ||||
|             fontSize: 21, | ||||
|             fontWeight: FontWeight.w600, | ||||
|             color: AppColors.blackColor, | ||||
|           ), | ||||
|         ), | ||||
|         Text( | ||||
|           LocaleKeys.selectFacilitiesSubTitle, | ||||
|           style: TextStyle( | ||||
|             fontSize: 16, | ||||
|             fontWeight: FontWeight.w500, | ||||
|             color: AppColors.greyTextColor, | ||||
|           ), | ||||
|         ), | ||||
|         SizedBox(height: 24.h), | ||||
|         FacilitySelectionItem( | ||||
|           svgPath: AppAssets.hmg, | ||||
|           title: "HMG".needTranslation, | ||||
|           subTitle: LocaleKeys.hospitalsWithCount.tr(namedArgs: { | ||||
|             'count': | ||||
|                 "${myAppointmentsViewModel.hospitalList?.registeredDoctorMap?[selectedRegion]?.hmgSize ?? 0}" | ||||
|           }), | ||||
|         ).onPress( | ||||
|           () { | ||||
|             regionalViewModel.setFacility(FacilitySelection.HMG.name); | ||||
|             regionalViewModel.setBottomSheetState( | ||||
|                 AppointmentViaRegionState.HOSPITAL_SELECTION); | ||||
|           }, | ||||
|         ), | ||||
|         SizedBox(height: 16.h), | ||||
|         FacilitySelectionItem( | ||||
|             svgPath: AppAssets.hmc, | ||||
|             title: "HMC".needTranslation, | ||||
|             subTitle: LocaleKeys.medicalCentersWithCount.tr(namedArgs: { | ||||
|               'count': | ||||
|                   "${myAppointmentsViewModel.hospitalList?.registeredDoctorMap?[selectedRegion]?.hmcSize ?? 0}" | ||||
|             })).onPress( | ||||
|           () { | ||||
|             regionalViewModel.setFacility(FacilitySelection.HMC.name); | ||||
|             regionalViewModel.setBottomSheetState( | ||||
|                 AppointmentViaRegionState.HOSPITAL_SELECTION); | ||||
|           }, | ||||
|         ), | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,109 @@ | ||||
| import 'package:easy_localization/easy_localization.dart' | ||||
|     show tr, StringTranslateExtension; | ||||
| import 'package:flutter/material.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/string_extensions.dart'; | ||||
| import 'package:hmg_patient_app_new/features/my_appointments/appointment_via_region_viewmodel.dart'; | ||||
| import 'package:hmg_patient_app_new/features/my_appointments/models/facility_selection.dart'; | ||||
| import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; | ||||
| import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; | ||||
| import 'package:hmg_patient_app_new/presentation/appointments/widgets/hospital_bottom_sheet/hospital_list_items.dart'; | ||||
| import 'package:hmg_patient_app_new/presentation/appointments/widgets/hospital_bottom_sheet/type_selection_widget.dart'; | ||||
| import 'package:hmg_patient_app_new/presentation/lab/collapsing_list_view.dart'; | ||||
| import 'package:hmg_patient_app_new/theme/colors.dart' show AppColors; | ||||
| import 'package:hmg_patient_app_new/widgets/input_widget.dart'; | ||||
| import 'package:provider/provider.dart'; | ||||
| 
 | ||||
| class HospitalBottomSheetBody extends StatelessWidget { | ||||
|   late MyAppointmentsViewModel appointmentsViewModel; | ||||
|   late AppointmentViaRegionViewmodel regionalViewModel; | ||||
|   final TextEditingController searchText = TextEditingController(); | ||||
| 
 | ||||
|   HospitalBottomSheetBody({super.key}); | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     appointmentsViewModel = Provider.of<MyAppointmentsViewModel>(context); | ||||
|     regionalViewModel = Provider.of<AppointmentViaRegionViewmodel>(context); | ||||
|     return Column( | ||||
|       crossAxisAlignment: CrossAxisAlignment.start, | ||||
|       children: [ | ||||
|         Text( | ||||
|           LocaleKeys.selectHospital.tr(), | ||||
|           style: TextStyle( | ||||
|             fontSize: 21, | ||||
|             fontWeight: FontWeight.w600, | ||||
|             color: AppColors.blackColor, | ||||
|           ), | ||||
|         ), | ||||
|         Text( | ||||
|           LocaleKeys.selectHospitalSubTitle.tr(), | ||||
|           style: TextStyle( | ||||
|             fontSize: 16, | ||||
|             fontWeight: FontWeight.w500, | ||||
|             color: AppColors.greyTextColor, | ||||
|           ), | ||||
|         ), | ||||
|         SizedBox(height: 16.h), | ||||
|         TextInputWidget( | ||||
|           labelText: LocaleKeys.search.tr(), | ||||
|           hintText: "Search Hospital".tr(), | ||||
|           controller: searchText, | ||||
|           onChange: (value) { | ||||
|             appointmentsViewModel.filterHospitalListByString(value, regionalViewModel.selectedRegionId , regionalViewModel.selectedFacilityType == | ||||
|                 FacilitySelection.HMG.name); | ||||
|           }, | ||||
|           isEnable: true, | ||||
|           prefix: null, | ||||
|           autoFocus: false, | ||||
|           isBorderAllowed: false, | ||||
|           keyboardType: TextInputType.text, | ||||
|           isAllowLeadingIcon: true, | ||||
|           selectionType: SelectionTypeEnum.search, | ||||
|           padding: EdgeInsets.symmetric( | ||||
|             vertical: ResponsiveExtension(10).h, | ||||
|             horizontal: ResponsiveExtension(15).h, | ||||
|           ), | ||||
|         ), | ||||
|         SizedBox(height: 24.h), | ||||
|         // TypeSelectionWidget( | ||||
|         //   hmcCount: "0", | ||||
|         //   hmgCount: "0", | ||||
|         // ), | ||||
|         // SizedBox(height: 21.h), | ||||
|         SizedBox( | ||||
|           height: MediaQuery.sizeOf(context).height * .4, | ||||
|           child: ListView.separated( | ||||
|               itemBuilder: (_, index) => HospitalListItem( | ||||
|                     hospitalData: regionalViewModel.selectedFacilityType == | ||||
|                             FacilitySelection.HMG.name | ||||
|                         ? appointmentsViewModel | ||||
|                             .filteredHospitalList! | ||||
|                             .registeredDoctorMap![ | ||||
|                                 regionalViewModel.selectedRegionId!]! | ||||
|                             .hmgDoctorList![index] | ||||
|                         : appointmentsViewModel | ||||
|                             .filteredHospitalList | ||||
|                             ?.registeredDoctorMap?[ | ||||
|                                 regionalViewModel.selectedRegionId!] | ||||
|                             ?.hmcDoctorList?[index], | ||||
|                     isLocationEnabled:  appointmentsViewModel.getLocationStatus(), | ||||
|                   ), | ||||
|               separatorBuilder: (_, __) => SizedBox( | ||||
|                     height: 16.h, | ||||
|                   ), | ||||
|               itemCount: (regionalViewModel.selectedFacilityType == | ||||
|                               FacilitySelection.HMG.name | ||||
|                           ? (appointmentsViewModel.filteredHospitalList?.registeredDoctorMap?[ | ||||
|                                   regionalViewModel.selectedRegionId]?.hmgDoctorList) | ||||
|                           : (appointmentsViewModel | ||||
|                               .filteredHospitalList | ||||
|                               ?.registeredDoctorMap?[ | ||||
|                                   regionalViewModel.selectedRegionId]?.hmcDoctorList))?.length ?? | ||||
|                   0), | ||||
|         ) | ||||
|       ], | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @ -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/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/extensions/string_extensions.dart'; | ||||
| import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; | ||||
| import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/doctor_list_api_response.dart'; | ||||
| import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/hospital_model.dart'; | ||||
| import 'package:hmg_patient_app_new/theme/colors.dart'; | ||||
| import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; | ||||
| 
 | ||||
| class HospitalListItem extends StatelessWidget { | ||||
|   final PatientDoctorAppointmentList? hospitalData; | ||||
|   final bool isLocationEnabled; | ||||
| 
 | ||||
|   late AppState appState; | ||||
| 
 | ||||
|   HospitalListItem( | ||||
|       {super.key, required this.hospitalData, required this.isLocationEnabled}); | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     appState = getIt.get<AppState>(); | ||||
|     return DecoratedBox( | ||||
|       decoration: RoundedRectangleBorder().toSmoothCornerDecoration( | ||||
|         color: AppColors.whiteColor, | ||||
|         borderRadius: 20.h, | ||||
|         hasShadow: false, | ||||
|       ), | ||||
|       child: Row( | ||||
|         mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|         children: [ | ||||
|           Expanded( | ||||
|             child: Column( | ||||
|               crossAxisAlignment: CrossAxisAlignment.start, | ||||
|               spacing: 8.h, | ||||
|               children: [hospitalName, distanceInfo], | ||||
|             ), | ||||
|           ), | ||||
|           Utils.buildSvgWithAssets( | ||||
|             icon: AppAssets.forward_arrow_icon, | ||||
|             iconColor: AppColors.blackColor, | ||||
|             width: 18, | ||||
|             height: 13, | ||||
|             fit: BoxFit.contain, | ||||
|           ), | ||||
|         ], | ||||
|       ).paddingSymmetrical(16.h, 16.h), | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   Widget get hospitalName => Row( | ||||
|         children: [ | ||||
|           Utils.buildSvgWithAssets( | ||||
|             icon: (hospitalData?.isHMC == true) ? AppAssets.hmc : AppAssets.hmg, | ||||
|           ).paddingOnly(right: 10), | ||||
|           Expanded( | ||||
|             child: Text( | ||||
|               hospitalData?.filterName ?? "", | ||||
|               style: TextStyle( | ||||
|                 fontWeight: FontWeight.w600, | ||||
|                 fontSize: 16, | ||||
|                 color: AppColors.blackColor, | ||||
|               ), | ||||
|             ), | ||||
|           ) | ||||
|         ], | ||||
|       ); | ||||
| 
 | ||||
|   Widget get distanceInfo => Row( | ||||
| 
 | ||||
|         children: [ | ||||
|           Visibility( | ||||
|               visible: (hospitalData?.distanceInKMs != "0"), | ||||
|               child: | ||||
| 
 | ||||
| 
 | ||||
|                 AppCustomChipWidget( | ||||
|                     labelText: | ||||
|                         "${hospitalData?.distanceInKMs ?? ""} km".needTranslation, | ||||
|                     deleteIcon: AppAssets.location_red, | ||||
|                     deleteIconSize: Size(9, 12), | ||||
|                     backgroundColor: AppColors.secondaryLightRedColor, | ||||
|                     textColor: AppColors.errorColor, | ||||
|                   ), | ||||
| 
 | ||||
| 
 | ||||
|   ), | ||||
|           Visibility( | ||||
|               visible: (hospitalData?.distanceInKMs == "0"), | ||||
|               child: Row( | ||||
|                 children: [ | ||||
|                   AppCustomChipWidget( | ||||
|                     labelText: "Distance not available".needTranslation, | ||||
|                     textColor: AppColors.blackColor, | ||||
|                   ), | ||||
|                   SizedBox(width: 8.h,) | ||||
| 
 | ||||
|                 ], | ||||
|               )), | ||||
|           Visibility( | ||||
|               visible: !isLocationEnabled, | ||||
|               child: AppCustomChipWidget( | ||||
|                 labelText: "Location turned off".needTranslation, | ||||
|                 deleteIcon: AppAssets.location_unavailable, | ||||
|                 deleteIconSize: Size(9, 12), | ||||
|                 textColor: AppColors.blackColor, | ||||
|               )), | ||||
|         ], | ||||
|       ); | ||||
| } | ||||
| @ -0,0 +1,93 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:hmg_patient_app_new/core/app_assets.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/my_appointments/models/facility_selection.dart'; | ||||
| import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart'; | ||||
| import 'package:hmg_patient_app_new/theme/colors.dart'; | ||||
| import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; | ||||
| import 'package:provider/provider.dart' show Consumer; | ||||
| 
 | ||||
| class TypeSelectionWidget extends StatelessWidget { | ||||
|   final String hmcCount; | ||||
|   final String hmgCount; | ||||
| 
 | ||||
|   const TypeSelectionWidget( | ||||
|       {super.key, required this.hmcCount, required this.hmgCount}); | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Consumer<MyAppointmentsViewModel>( | ||||
|       builder: (_, data, __) => Row( | ||||
|         spacing: 8, | ||||
|         mainAxisSize: MainAxisSize.max, | ||||
|         children: [ | ||||
|           AppCustomChipWidget( | ||||
|             labelText: "All Facilities".needTranslation, | ||||
|             shape: RoundedRectangleBorder( | ||||
|                 side: BorderSide( | ||||
|                   color: data.currentlySelectedFacility == FacilitySelection.ALL | ||||
|                       ? AppColors.errorColor | ||||
|                       : AppColors.chipBorderColorOpacity20, | ||||
|                   width: 1, | ||||
|                 ), | ||||
|                 borderRadius: BorderRadius.circular(10)), | ||||
|             backgroundColor: | ||||
|                 data.currentlySelectedFacility == FacilitySelection.ALL | ||||
|                     ? AppColors.secondaryLightRedColor | ||||
|                     : AppColors.whiteColor, | ||||
|             textColor: data.currentlySelectedFacility == FacilitySelection.ALL | ||||
|                 ? AppColors.errorColor | ||||
|                 : AppColors.blackColor, | ||||
|           ).onPress((){ | ||||
|             data.setSelectedFacility(FacilitySelection.ALL); | ||||
|           }), | ||||
|           AppCustomChipWidget( | ||||
|             icon: AppAssets.hmg, | ||||
|             iconHasColor: false, | ||||
|             labelText: "Hospitals".needTranslation, | ||||
|             shape: RoundedRectangleBorder( | ||||
|                 side: BorderSide( | ||||
|                   color: data.currentlySelectedFacility == FacilitySelection.HMG | ||||
|                       ? AppColors.errorColor | ||||
|                       : AppColors.chipBorderColorOpacity20, | ||||
|                   width: 1, | ||||
|                 ), | ||||
|                 borderRadius: BorderRadius.circular(10)), | ||||
|             backgroundColor: | ||||
|                 data.currentlySelectedFacility == FacilitySelection.HMG | ||||
|                     ? AppColors.secondaryLightRedColor | ||||
|                     : AppColors.whiteColor, | ||||
|             textColor: data.currentlySelectedFacility == FacilitySelection.HMG | ||||
|                 ? AppColors.errorColor | ||||
|                 : AppColors.blackColor, | ||||
|           ).onPress((){ | ||||
|             data.setSelectedFacility(FacilitySelection.HMG); | ||||
|           }), | ||||
|           AppCustomChipWidget( | ||||
|             icon: AppAssets.hmc, | ||||
|             iconHasColor: false, | ||||
|             labelText: "Medical Centers".needTranslation, | ||||
|             shape: RoundedRectangleBorder( | ||||
|                 side: BorderSide( | ||||
|                   color: data.currentlySelectedFacility == FacilitySelection.HMC | ||||
|                       ? AppColors.errorColor | ||||
|                       : AppColors.chipBorderColorOpacity20, | ||||
|                   width: 1, | ||||
|                 ), | ||||
|                 borderRadius: BorderRadius.circular(10)), | ||||
|             backgroundColor: | ||||
|             data.currentlySelectedFacility == FacilitySelection.HMC | ||||
|                 ? AppColors.secondaryLightRedColor | ||||
|                 : AppColors.whiteColor, | ||||
|             textColor: data.currentlySelectedFacility == FacilitySelection.HMC | ||||
|                 ? AppColors.errorColor | ||||
|                 : AppColors.blackColor, | ||||
|           ).onPress((){ | ||||
|             data.setSelectedFacility(FacilitySelection.HMC); | ||||
|           }), | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,114 @@ | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/material.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'; | ||||
| 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/theme/colors.dart' show AppColors; | ||||
| import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; | ||||
| 
 | ||||
| class RegionListItem extends StatelessWidget { | ||||
|   final String title; | ||||
|   final String hmcCount; | ||||
|   final String hmgCount; | ||||
|   final String subTitle; | ||||
| 
 | ||||
|   const RegionListItem( | ||||
|       {super.key, | ||||
|       required this.title, | ||||
|       required this.subTitle, | ||||
|       required this.hmcCount, | ||||
|       required this.hmgCount}); | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Container( | ||||
|       decoration: RoundedRectangleBorder().toSmoothCornerDecoration( | ||||
|         color: AppColors.whiteColor, | ||||
|         borderRadius: 20.h, | ||||
|         hasShadow: false, | ||||
|       ), | ||||
|       child: Column( | ||||
|         mainAxisAlignment: MainAxisAlignment.start, | ||||
|         children: [ | ||||
|           header, | ||||
|           Row( | ||||
|             mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|             children: [ | ||||
|               Row( | ||||
|                 spacing: 8.h, | ||||
|                 children: [ | ||||
|                   placesCountItem( | ||||
|                       AppAssets.hmg, hmgCount, " ${LocaleKeys.hospital.tr()}"), | ||||
|                   placesCountItem(AppAssets.hmc, hmcCount, | ||||
|                       " ${LocaleKeys.medicalCenters.tr()}"), | ||||
|                 ], | ||||
|               ), | ||||
|               Utils.buildSvgWithAssets( | ||||
|                 icon: AppAssets.forward_arrow_icon, | ||||
|                 iconColor: AppColors.blackColor, | ||||
|                 width: 18, | ||||
|                 height: 13, | ||||
|                 fit: BoxFit.contain, | ||||
|               ), | ||||
|             ], | ||||
|           ) | ||||
|         ], | ||||
|       ).paddingAll(16.h), | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   Widget placesCountItem(String svgPath, String count, String title) { | ||||
|     return AppCustomChipWidget( | ||||
|       iconSize: 14, | ||||
|       icon: svgPath, | ||||
|       iconHasColor: false, | ||||
|       richText: RichText( | ||||
|                   text: TextSpan( | ||||
|                       text: count, | ||||
|                       style: TextStyle( | ||||
|                           fontSize: 12.h, | ||||
|                           fontWeight: FontWeight.w700, | ||||
|                           color: AppColors.blackColor), | ||||
|                       children: [ | ||||
|                     TextSpan( | ||||
|                         text: title, | ||||
|                         style: TextStyle( | ||||
|                             fontSize: 12.h, | ||||
|                             fontWeight: FontWeight.w500, | ||||
|                             color: AppColors.blackColor)) | ||||
|                   ])), | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|  Widget get header => Column( | ||||
|         mainAxisAlignment: MainAxisAlignment.start, | ||||
|         crossAxisAlignment: CrossAxisAlignment.start, | ||||
|         children: [ | ||||
|           Align( | ||||
|             alignment: Alignment.centerLeft, | ||||
|             child: Text( | ||||
|               title, | ||||
|               style: TextStyle( | ||||
|                 fontSize: 16.h, | ||||
|                 fontWeight: FontWeight.w600, | ||||
|                 color: AppColors.blackColor, | ||||
|               ), | ||||
|             ), | ||||
|           ), | ||||
|           Align( | ||||
|             alignment: Alignment.centerLeft, | ||||
|             child: Text( | ||||
|               subTitle, | ||||
|               style: TextStyle( | ||||
|                 fontSize: 12.h, | ||||
|                 fontWeight: FontWeight.w500, | ||||
|                 color: AppColors.greyTextColor, | ||||
|               ), | ||||
|             ), | ||||
|           ), | ||||
|         ], | ||||
|       ); | ||||
| } | ||||
| @ -0,0 +1,86 @@ | ||||
| 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/core/utils/utils.dart' show Utils; | ||||
| import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; | ||||
| import 'package:hmg_patient_app_new/features/my_appointments/appointment_via_region_viewmodel.dart'; | ||||
| import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart' | ||||
|     show MyAppointmentsViewModel; | ||||
| import 'package:hmg_patient_app_new/presentation/appointments/widgets/region_bottomsheet/region_list_item.dart' | ||||
|     show RegionListItem; | ||||
| import 'package:provider/provider.dart'; | ||||
| 
 | ||||
| class RegionBottomSheetBody extends StatefulWidget { | ||||
| 
 | ||||
|   const RegionBottomSheetBody({super.key}); | ||||
| 
 | ||||
|   @override | ||||
|   State<RegionBottomSheetBody> createState() => _RegionBottomSheetBodyState(); | ||||
| } | ||||
| 
 | ||||
| class _RegionBottomSheetBodyState extends State<RegionBottomSheetBody> { | ||||
|   late MyAppointmentsViewModel myAppointmentsViewModel; | ||||
|   late AppointmentViaRegionViewmodel regionalViewModel; | ||||
| 
 | ||||
|   @override | ||||
|   void initState() { | ||||
|     scheduleMicrotask(() { | ||||
|       myAppointmentsViewModel.getRegionMappedProjectList(); | ||||
|     }); | ||||
|     super.initState(); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     myAppointmentsViewModel = Provider.of<MyAppointmentsViewModel>(context); | ||||
|     regionalViewModel = Provider.of<AppointmentViaRegionViewmodel>(context); | ||||
|     return Consumer<MyAppointmentsViewModel>( | ||||
|       builder: (context, myAppointmentsVM, child) { | ||||
|         if (myAppointmentsVM.isRegionListLoading) { | ||||
|           return Container( | ||||
|             height: MediaQuery.of(context).size.height * 0.3, | ||||
|             decoration: const BoxDecoration( | ||||
|               color: Colors.white, | ||||
|               borderRadius: BorderRadius.vertical(top: Radius.circular(16)), | ||||
|             ), | ||||
|             child: Center( | ||||
|               child: Utils.getLoadingWidget(), | ||||
|             ), | ||||
|           ); | ||||
|         } else { | ||||
|           return SizedBox( | ||||
|             height: MediaQuery.of(context).size.height * 0.5, | ||||
|             child: ListView.separated( | ||||
|               itemCount: | ||||
|                   myAppointmentsVM.hospitalList?.registeredDoctorMap?.length ?? | ||||
|                       0, | ||||
|               separatorBuilder: (_, __) { | ||||
|                 return SizedBox( | ||||
|                   height: 16.h, | ||||
|                 ); | ||||
|               }, | ||||
|               itemBuilder: (_, index) { | ||||
|                 String key = myAppointmentsVM | ||||
|                         .hospitalList?.registeredDoctorMap?.keys | ||||
|                         .toList()[index] ?? | ||||
|                     ''; | ||||
|                 return RegionListItem( | ||||
|                   title: key, | ||||
|                   subTitle: "", | ||||
|                   hmcCount: | ||||
|                       "${myAppointmentsVM.hospitalList?.registeredDoctorMap?[key]?.hmcSize ?? 0}", | ||||
|                   hmgCount: | ||||
|                       "${myAppointmentsVM.hospitalList?.registeredDoctorMap?[key]?.hmgSize ?? 0}", | ||||
|                 ).onPress(() { | ||||
|                   regionalViewModel.setSelectedRegionId(key); | ||||
|                   regionalViewModel.setBottomSheetState(AppointmentViaRegionState.TYPE_SELECTION); | ||||
|                 }); | ||||
|               }, | ||||
|             ), | ||||
|           ); | ||||
|         } | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,44 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| 
 | ||||
| class ProfileSelector extends StatelessWidget { | ||||
|   final List<Map<String, dynamic>> profiles; | ||||
|   final Function(Map<String, dynamic>) onSelect; | ||||
| 
 | ||||
|   const ProfileSelector({ | ||||
|     Key? key, | ||||
|     required this.profiles, | ||||
|     required this.onSelect, | ||||
|   }) : super(key: key); | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Column( | ||||
|       mainAxisSize: MainAxisSize.min, | ||||
|       children: profiles.map((profile) { | ||||
|         return ListTile( | ||||
|           leading: CircleAvatar( | ||||
|             radius: 22, | ||||
|             backgroundImage: profile["GenderImage"] != null && | ||||
|                 profile["GenderImage"].toString().isNotEmpty | ||||
|                 ? NetworkImage(profile["GenderImage"]) | ||||
|                 : AssetImage( | ||||
|                 profile["Gender"] == 1 | ||||
|                     ? "assets/images/male.png" | ||||
|                     : "assets/images/female.png") | ||||
|             as ImageProvider, | ||||
|           ), | ||||
|           title: Text( | ||||
|             profile["PatientName"] ?? "Unknown", | ||||
|             style: const TextStyle(fontWeight: FontWeight.w600), | ||||
|           ), | ||||
|           subtitle: Text( | ||||
|             profile["Relationship"] ?? "Self", | ||||
|             style: const TextStyle(color: Colors.grey), | ||||
|           ), | ||||
|           trailing: const Icon(Icons.arrow_forward_ios, size: 16), | ||||
|           onTap: () => onSelect(profile), | ||||
|         ); | ||||
|       }).toList(), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,15 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import '../common_bottom_sheet.dart'; | ||||
| import 'my_Family.dart'; | ||||
|  class MyFamilySheet { | ||||
|    static void show(BuildContext context, List<Map<String, dynamic>> profiles, Function(Map<String, dynamic>) onSelect) { | ||||
|      showCommonBottomSheetWithoutHeight( | ||||
|        context, | ||||
|        title: 'Select Profile', | ||||
|        child: ProfileSelector(profiles: profiles, onSelect: (profile) { | ||||
|          Navigator.of(context).pop(); // Close the bottom sheet | ||||
|          onSelect(profile); // Call the onSelect callback | ||||
|        }), callBackFunc: () {}, | ||||
|      ); | ||||
|    } | ||||
|  } | ||||
					Loading…
					
					
				
		Reference in New Issue