From 4cb7b6093ce1d0d2ce8138a8ad9f2a75a37d08b7 Mon Sep 17 00:00:00 2001 From: Sneha Date: Thu, 14 Mar 2024 12:57:45 +0530 Subject: [PATCH] patient dashboard --- android/app/src/main/AndroidManifest.xml | 2 + images/bmi.png | Bin 3175 -> 7949 bytes images/bp.png | Bin 0 -> 5020 bytes images/get_checkup.png | Bin 0 -> 6927 bytes images/health_records.png | Bin 0 -> 3784 bytes images/medicines.png | Bin 6187 -> 6214 bytes images/messages.png | Bin 0 -> 3825 bytes images/new_problem.png | Bin 0 -> 6114 bytes images/prescriptions.png | Bin 4900 -> 4975 bytes images/reports.png | Bin 3826 -> 0 bytes images/resources.png | Bin 0 -> 6300 bytes images/sugar.png | Bin 0 -> 6416 bytes lib/common/dashboard.dart | 43 +- lib/common/settings.dart | 841 +++++++- lib/models/all_problems_model.dart | 33 + lib/models/bmi_history_model.dart | 55 + lib/models/bp_history_model.dart | 34 + lib/models/get_connected_doctors_model.dart | 30 + lib/models/prescriptions_model.dart | 40 + lib/models/reports_model.dart | 45 + lib/models/sugar_history_model.dart | 62 + .../BMI/bmi_caluculator.dart | 539 +++++ lib/patient_dashboard/BMI/bmi_history.dart | 424 ++++ lib/patient_dashboard/BP/bp_calculator.dart | 228 +++ lib/patient_dashboard/BP/bp_history.dart | 372 ++++ .../Reports/add_reports.dart | 1274 ++++++++++++ .../Reports/all-records_onclick_new.dart | 1813 +++++++++++++++++ lib/patient_dashboard/Reports/allreports.dart | 1294 ++++++++++++ .../Reports/update_report.dart | 1190 +++++++++++ .../Sugar/sugar_calculator.dart | 257 +++ .../Sugar/sugar_history.dart | 354 ++++ lib/patient_dashboard/patient_dashboard.dart | 159 ++ .../patient_dshboard_details.dart | 245 +++ .../prescriptions/add_prescriptions.dart | 418 ++++ .../prescriptions/prescriptions.dart | 976 +++++++++ .../problems/all_problems.dart | 1058 ++++++++++ .../problems/video_file.dart | 59 + lib/video_call/video_call.dart | 19 + pubspec.lock | 7 + pubspec.yaml | 1 + 40 files changed, 11863 insertions(+), 9 deletions(-) create mode 100644 images/bp.png create mode 100644 images/get_checkup.png create mode 100644 images/health_records.png create mode 100644 images/messages.png create mode 100644 images/new_problem.png delete mode 100644 images/reports.png create mode 100644 images/resources.png create mode 100644 images/sugar.png create mode 100644 lib/models/all_problems_model.dart create mode 100644 lib/models/bmi_history_model.dart create mode 100644 lib/models/bp_history_model.dart create mode 100644 lib/models/get_connected_doctors_model.dart create mode 100644 lib/models/prescriptions_model.dart create mode 100644 lib/models/reports_model.dart create mode 100644 lib/models/sugar_history_model.dart create mode 100644 lib/patient_dashboard/BMI/bmi_caluculator.dart create mode 100644 lib/patient_dashboard/BMI/bmi_history.dart create mode 100644 lib/patient_dashboard/BP/bp_calculator.dart create mode 100644 lib/patient_dashboard/BP/bp_history.dart create mode 100644 lib/patient_dashboard/Reports/add_reports.dart create mode 100644 lib/patient_dashboard/Reports/all-records_onclick_new.dart create mode 100644 lib/patient_dashboard/Reports/allreports.dart create mode 100644 lib/patient_dashboard/Reports/update_report.dart create mode 100644 lib/patient_dashboard/Sugar/sugar_calculator.dart create mode 100644 lib/patient_dashboard/Sugar/sugar_history.dart create mode 100644 lib/patient_dashboard/patient_dashboard.dart create mode 100644 lib/patient_dashboard/patient_dshboard_details.dart create mode 100644 lib/patient_dashboard/prescriptions/add_prescriptions.dart create mode 100644 lib/patient_dashboard/prescriptions/prescriptions.dart create mode 100644 lib/patient_dashboard/problems/all_problems.dart create mode 100644 lib/patient_dashboard/problems/video_file.dart create mode 100644 lib/video_call/video_call.dart diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 11eda48..9f2ee76 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -14,6 +14,8 @@ + + `4Jg9vU=JuNXU}pzi9z$4=%dC?(;g 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 literal 3175 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

+lkw0MwY1iBzU>7A8-SpT4_c%4 zV2$UCRc+quNtlJ^4(11M4{fEn#Z2gm50aRBpq5AoAXL$E+AjrF>tK*rU8lM8Qgp`> zqS1Cr=sunDAO`KEf5{=WEr0M*Ef@<^a(OA`)q%I$D<2AkYi2!QvTq_eh$pHFp(pYT zVY3!83W?4qVD^Fl<#h+w3emmmKJnJKaaxO&8Se)lNmoEgD9e1${HOj!TDIuC&9SUw zI?=#vg`uzG!_nGqDstm5j(ew@D_lZ!#OuHQsTol4s!k4?zgDm;<`vgD*iC51Aoz8 zh?Q3?#@;Pw)pt0bYTc`^n~h$ZGB8uqt-GR}CGR)g3ZYu(zP_Pj8EN1?8x=iKRR14e z!AjBVRXpP2(Y@i&{*C5|t2R&S6p@??XLyO{hWv{ufmd(r{x|LL6l;I>%5r*fKfWqK z2gEyi3l7-f#`^GqRv!2Lu5IWIiFe}vzu>0&hwe%91TaMA`M}=+0npbm(SD6^jQ$@Y Cj2dJB diff --git a/images/bp.png b/images/bp.png new file mode 100644 index 0000000000000000000000000000000000000000..fb6f13caa61fee90defa3bb47b95482390ed227e GIT binary patch literal 5020 zcmb_gWl$STw+;}zc(Gt9S}27gMT3T>XrX9vPm2Y2hvM!YiWP^pxP{_Yyl9aY4gR7j zetExNcfOx@?#}Ma&XJWfXP@)TMrpixO+o}B0ssIcN{R}a000*Gzk>kpLE=U9j2Zx- zvQ$!#)AqtTSYAeGy+;ik-`DK}FWw4GAw%lPY->LKA!^NJ0E|fxIyl(;eC#~o)L2@t zTu5J5ul@<2ngm36N(0Nr`HjaJ^X!8UZZp1NPkmay6df?W1L=L&h{J9&!awrR?*iE8 z`aE*U_w(<^+Xx;u|9@(1@2%pO&-ni$=Z(7}7lsYKxGKMJg>G zwt1;ZE6%UYN(aCSnd8Hi^gXmy36iD&i&;JQa_Wg217e>A1LPvY=_<(2!X73uUANzj zb%5vxVeSC-nQRbP^XUaXmJe8#yr+_20tX8lEPxG^wEz+X_5Sbcz=8mZu>h<@y8kwC zuEN>scj#2nvhPf+} z4$EW{y+v;=x?bv|n#x&d5F&`n$|l^e1msrP;SpTdZBrE>&29N|#mHVZ*+d)hIr}7v zumLO*ia9P9sT3IBUZFkhCywOc!Q9+Tr8g&qMBc<$A*z$8gtKkmN5fUb z*$>Bv=4!CXv_L&1#02e+ZEX*S9#o=1*X^bZfhBVh)WcmMO{HrLX=Y0&a5q6UqxD`)GhJ{8A0cT;y z@N7o8nSYl(zTzIP-rU9RHvTgq{QI+SDvMhlPuBRZMIYkgdpIsS8-ni%v^>|`9hsiq z62a}VzX<-|gy!v={f5Z1x6)$pup9T|t=sUW><&>)DCxXGY)WOh3ekccFG3YX#aJH~ zGqJms#YOmjeKW%#Qr`%6MZmF(jos1R6?<%?@kK;6PzTRnrVEdMq)lYEWpGw{*qXY3A|aZdL$@CLLh@v3%&mig*zV48Tw0$`_sDy>ptb}j@z!&g|3auR$g?B%pb{WXX3 z`qnzjxN2%k$12*0=uQMvmnuXLmhvd9Xl*Rd*PU@Tvsw3eT~aio*hKC;OTVTz?mVPE z$uRq^S5A-)?7y$jaJO^VQ<_|uqIX1-z%(KwdA!}mRQbX;ERtc(8oHADAzw4$^ZNWe z_oX=Jb62djY(C@e9>iy949~Y*6Ql+&S0re33ndpmSk|zRB#7=`MO9)*C@}RREvw~W%mfF8HcN!{Q&|g)37ro_y80il zTl8OzB5b9%b{lpOHF}5EVkvQF8Y@m&d%ybu4J?U|Orv+W{{|EQpYW~`usFa$)2Wa-PU(0`G! z-HmQd59lt^tt4Y)rt6#xi}Y^?^N&p&QShr^B`wbxG-}z)r0UJyBxwg~JI|x3I$9p3Zvx^&lZ>H#EGMzx^*a1~^!@vlA)^ z;k-TP7V<6J(9i}KV-lQ_&? z5YH!|=86R*f@*A0#Szcxt`f_=!6X9C#93!QFQWJ}Fs=K&%*t#t4m6Y8s4JCzsv{gZ zy)2?c=A0o_Hyq1lw7!MUy*{?I&$2{q%G4y?gEA*-v4qG5VYamB=G}hg*3QQuRR{EY zRDWuq`8l}P3E`PVoX9-VOngwpK`h95)p1fSWNR_cpv_XWoy}nLXw}1uqd`08RUK!F zoq4OH83aW>sicDZ*_kmPrLyCA7ArQijpM!^zM)lX4_D&EDQ<}Um3wrO2#>VCu4KDD za~khBj5=_s|6E<%F)38Ie4^)uzA$4eZC1&xG2PAMY-N1z-Vu7zT(3GtYFau~GR0sfO>M_-70%(I%!y9#Y-PB0{QREqEeB`X z&gP9>S15y2eEQFiysfqy3!Zno8cbDJ;Zw8)sB)jM2!{IS*5Z($0BbmpFQXLo7)e2N zK(d=}E?!j9Z6R^6l+;|$OMWDC#=7r;l&a*11%nhlRQ(oqv&Wa`X9BNUjlCi4kQcOq zEMR45uMUB_6rm$#QRK_ZnFZdqC#K~?sIk?u#wKu8CrC3e3+a*o`pMhGUCNXQx0d?-}uRQqBNU*HsN*xj_^Wk@reMO48+y58qj21 zvYH%B(bE*8+MG4pA}l-mLpzA^L!J?*H7$D$&Ws-)H%qA#IinpAe``q9G=I<< zdEr8-dvdbIU4Z459Ru(-Y|B^RS2ti2oz(gyL+rune6joUAD9y<8GPIbNgTRjWPO1I zNRfjhH+Y0-k_x!6flRHAqXg}8L7$)qqQ(dX5pu9tv9bSSTr>_=2(;DV5eeg~px+G+ zfepM+X5y$zLC;g!38f~!`Hb7wZn+j3+F;i=qRJ1f4D%5``4e`QmSZEFaTMO0Nd{Dm zU67oect&@;LP40ZeBN>){q(yAK_VS;1MVa&&(>348~kSy|Gy~Ws5{rL^U%?ZRp(Pz z#qpu2?CZ(J*0;mSto(P3mR3tf_=?vW<&uICs8hXLw5wXqfX3M75iqof5a++CW~N;_ zMPUIs*mbyhGCi{meh$eT?98Bm20aP}WNGQP4~oVsT{8Z$F}J)k>HkPAX8|0{b&)%^ z{2_(AT%Zacd>+Ul@)+ZAtM?y`L8>3Q=jsE5Yw0Mmp(-j&i0&G>9!PAK)`5O=TG=(^ zSUQn@?N0iA5yEp6)NQF~|5Uj6-|7if_d)%sO0#Y2ImEZ?7#`Qt^+kED-cEP8CO5q= zA#;=oJkXIUL!|k5kT%YBJWg0SL=JfB843!mH9FKM;6k6shClXM!S7$Rs2%9&IP7&_ z8j7;R@brg!7B{{NK%HMJZ_sXT_*<&Iz53_kltnTq}acFrWZ{qgl);;$4W<}mN~@zZrx$t@_c#K#6Qs|KUAO*jl5onl36uQ z@Qtm3rDuAR!(8$Q9}PxbLavzGwz0oGxM2x;GD&gK1 z>j9-R8X$FCXc3u}Li@zu`@bjM1uZmOohaikBHPNg({CxzT$@w<2PFX#G7L4VYZ?5~ zhh8{0n1(zu7ft>>qxksz*YYHxLa!Y=>6XYI$fw*{m*$p{?zMd5tj+Rsx#QV=CnO^chWbkWeEaN<~_0MoePS-Y7Nhvr=V4L zX{rCa z^^Y%mr+>dQ92RV{vd7qlNri*{NzmhI7B%J)L)E*GS;p=$rFdigCvJob9=mVq}9c3o)%TfxNnJp1>B6Jt>k^aoru@L44KY|!V@BB>H~WR118;j z4|h_X_4*)8ZanR}ApR265)sM4^w+RiDXCu$hwmS$*md=wazg1yu>`UHrD9^v2S{De zYZ6R{}{ynvZRWB49q|%n!d{ZT*9%P@tg8v*f{{c$3`B?+Y9tB~< zH^>Z<*k@J-8rq-U2WS#8tNXG3YJb2W_8*3M`|cl{je0~dVsXnHBd0FGR;rSU!#@9( z-LaTk1)Nu!kWUrVAdx|D&AXme&;AuRCS31FNUK%6v-b8g#hR~qtUsM r8W-~8cs6Pm*#A$zP5-xLT-RkRZiMb{Y?fF4T|nv88-*HqvylG*DXUgu literal 0 HcmV?d00001 diff --git a/images/get_checkup.png b/images/get_checkup.png new file mode 100644 index 0000000000000000000000000000000000000000..ce84c7c3a3e7652454bae7ebda1351c35eae081a GIT binary patch literal 6927 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 literal 0 HcmV?d00001 diff --git a/images/health_records.png b/images/health_records.png new file mode 100644 index 0000000000000000000000000000000000000000..1776224fa18a7a666de08db40bbd0bcfe2335248 GIT binary patch literal 3784 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 I$&Ug51J3x_@&Et; literal 6187 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 diff --git a/images/messages.png b/images/messages.png new file mode 100644 index 0000000000000000000000000000000000000000..c89a8c1db1f46047e54a2f08581d2f9d8d6d30e5 GIT binary patch literal 3825 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 literal 0 HcmV?d00001 diff --git a/images/prescriptions.png b/images/prescriptions.png index 5737a33e2b66dfba9c6bcabbd8dad366bcf85da3..a0b3dee352adab5110669e97a462bc27a4788f26 100644 GIT binary patch literal 4975 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 diff --git a/images/resources.png b/images/resources.png new file mode 100644 index 0000000000000000000000000000000000000000..ddc8acbe6aaec0ac0a3eb687999c527d4567e04a GIT binary patch literal 6300 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 X7+v%(_Q_81f66GoQHNB@nFjwC3-t4` literal 0 HcmV?d00001 diff --git a/images/sugar.png b/images/sugar.png new file mode 100644 index 0000000000000000000000000000000000000000..34c9b37fb1e2754bc49a0a762a64bfd5261f1fb1 GIT binary patch literal 6416 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 { ), ], ), - /*Column( + Column( children: [ GestureDetector( child: Container( @@ -160,23 +161,23 @@ class _DashboardState extends State { shape: BoxShape.circle, image: DecorationImage( image: AssetImage( - "images/reports.png"), // picked file + "images/myconnections.png"), // picked file fit: BoxFit.fitWidth)), ), onTap: () { - *//*Navigator.push( + Navigator.push( context, MaterialPageRoute( - builder: (context) => const AllReports()), - );*//* + builder: (context) => const PatientDashboard()), + ); }, ), Text( - 'Records', + 'Patient Dashboard', style: dashboardTextStyle(), ), ], - ),*/ + ), ], ), ), @@ -622,6 +623,34 @@ class _DashboardState extends State { ); }, ), + Divider( + color: Colors.grey, + ), + ListTile( + title: Row( + children: [ + Image( + image: const AssetImage('images/editprofile.png'), + height: 25, + width: 25, + fit: BoxFit.fill), + const SizedBox( + width: 10, + ), + const SizedBox( + width: 10, + ), + Text('Video Call', style: drawerListItemsTextStyle()), + ], + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const UpdateProfile()), + ); + }, + ), /*Divider( color: Colors.grey, ), diff --git a/lib/common/settings.dart b/lib/common/settings.dart index 31dea47..367008d 100644 --- a/lib/common/settings.dart +++ b/lib/common/settings.dart @@ -199,6 +199,48 @@ InputDecoration textFormFieldDecoration(IconData icon, var text) { ); } +InputDecoration textFormFieldDecorationGrey(IconData icon, var text) { + return InputDecoration( + prefixIcon: Icon( + icon, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: text, + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ); +} + +InputDecoration textFormFieldDecorationInsideApp(IconData icon, var text) { + return InputDecoration( + prefixIcon: Icon( + icon, + color: primaryColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + labelText: text, + labelStyle: TextStyle( + color: primaryColor, //<-- SEE HERE + ), + ); +} + InputDecoration textFormFieldDecorationBMI(IconData icon, var text) { return InputDecoration( //filled: true, @@ -216,7 +258,7 @@ InputDecoration textFormFieldDecorationBMI(IconData icon, var text) { ), labelText: text, labelStyle: TextStyle( - //color: Colors.black, //<-- SEE HERE + color: Colors.grey, //<-- SEE HERE ), ); } @@ -283,9 +325,37 @@ class AppSettings { static String generateQRCodeUrl = host + 'generate-qrcode-doctor'; static String getAllConectedPatientsDataUrl = host + 'customerDetails'; static String getRecordsDataUrl = host + 'getAllRecords'; + static String deleteRecordUrl = host + 'deleteRecord'; static String getDynamicCodeUrl = host + 'records'; static String dynamicCodeVerificationUrl = host + 'verifyDynamicCode'; - + static String getPatientInformationBasedOnMobileNumberUrl = host + 'getInfoCustomerDataPhone'; + static String getBmiHistoryUrl = host + 'usersbmi'; + static String getBpHistoryUrl = host + 'usersbp'; + static String getSugarHistoryUrl = host + 'userssugar'; + static String bmiCaluculateUrl = host + 'insertBMI'; + static String bpCaluculateUrl = host + 'insertBP'; + static String sugarCaluculateUrl = host + 'insertSugar'; + static String deleteBMIDetailsUrl = host + 'deleteBMI'; + static String deleteBPDetailsUrl = host + 'deleteBP'; + static String deleteSugarDetailsUrl = host + 'deleteSugar'; + static String findingsUploadPicUrl = host + 'uploads-findings-prescription'; + static String addFindingsUrl = host + 'update-uploads-findingsPictureId-prescription'; + static String addReportsUrl = host + 'update-uploads-reportsPictureId-prescription'; + static String addPrescriptionsUrl = host + 'update-uploads-prescriptionPictureId-prescription'; + static String updateFindingsUploadPicUrl = host + 'update-uploads-findings-prescription'; + static String updateReportsUploadPicUrl = host + 'update-uploads-reports-prescription'; + static String reportsUploadPicUrl = host + 'uploads-reports-prescription'; + static String prescriptionUploadPicUrl = host + 'uploads-prescription-prescription'; + static String updatePrescriptionPicUrl = host + 'update-uploads-prescription-prescription'; + static String deleteRecordsUrl = host + 'delete-url'; + static String updateRecordsUrl = host + 'records'; + static String deleteFindingsUrl = host + 'delete-uploads-findings'; + static String deletePrescriptionsUrl = host + 'delete-prescription'; + static String deleteReportsUrl = host + 'delete-report'; + static String getAllConnectedDoctorsDataUrl = host + 'connected-doctors'; + static String addRecordsUrl = host + 'add-record'; + static String addPrescriptionUrl = host + 'add-prescription-details'; + static String getAllReportProblemDetalisUrl = host + 'userreport'; static File? updatedImage; @@ -615,6 +685,37 @@ class AppSettings { } } + static Future deleteRecord(recordId) async { + var uri = Uri.parse(deleteRecordUrl + '/' + recordId); + + try { + var response = await http.delete(uri, headers: await buildRequestHeaders()); + + if (response.statusCode == 200) { + return true; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.delete(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return true; + } else { + return false; + } + } else { + return false; + } + } else { + return false; + } + } catch (e) { + print(e); + return false; + } + } + + + static Future getDynamicCode(payload) async { var uri = Uri.parse(getDynamicCodeUrl ); //uri = uri.replace(query: 'customerId=$customerId'); @@ -662,6 +763,742 @@ class AppSettings { } } + static Future getPatientInformationBasedOnMobileNumber(phoneNumber) async { + var uri = Uri.parse(getPatientInformationBasedOnMobileNumberUrl + '/' + phoneNumber); + //uri = uri.replace(query: 'customerId=$customerId'); + + var response = await http.get(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.get(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else { + return ''; + } + } else { + return ''; + } + } else { + return ''; + } + } + + static Future getBmiHistory(var customerId) async { + var uri = Uri.parse(getBmiHistoryUrl + '/' + customerId); + + var response = await http.get(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.get(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else { + return ''; + } + } else { + return ''; + } + } else { + return ''; + } + } + + static Future getBPHistory(var customerId) async { + var uri = Uri.parse(getBpHistoryUrl + '/' + customerId); + + var response = await http.get(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.get(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else { + return ''; + } + } else { + return ''; + } + } else { + return ''; + } + } + + static Future getSugarHistory(var customerId) async { + var uri = Uri.parse(getSugarHistoryUrl + '/' + customerId); + + var response = await http.get(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.get(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else { + return ''; + } + } else { + return ''; + } + } else { + return ''; + } + } + + static Future calculateBmi(payload,customerId) async { + var uri = Uri.parse(bmiCaluculateUrl + '/' + customerId); + + var response = await http.post(uri, + body: json.encode(payload), headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.post(uri, + body: json.encode(payload), headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else { + return ''; + } + } else { + return ''; + } + } else { + return ''; + } + } + + static Future calculateBP(payload,customerId) async { + var uri = Uri.parse(bpCaluculateUrl + '/' + customerId); + + var response = await http.post(uri, + body: json.encode(payload), headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.post(uri, + body: json.encode(payload), headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else { + return ''; + } + } else { + return ''; + } + } else { + return ''; + } + } + + static Future calculateSugar(payload,customerId) async { + var uri = Uri.parse(sugarCaluculateUrl + '/' + customerId); + + var response = await http.post(uri, + body: json.encode(payload), headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.post(uri, + body: json.encode(payload), headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else { + return ''; + } + } else { + return ''; + } + } else { + return ''; + } + } + + static Future deleteBMIDetails(bmiId,customerId) async { + var uri = Uri.parse(deleteBMIDetailsUrl + '/' + customerId+'/'+ bmiId); + + try { + var response = await http.delete(uri, headers: await buildRequestHeaders()); + + if (response.statusCode == 200) { + return true; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.delete(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return true; + } else { + return false; + } + } else { + return false; + } + } else { + return false; + } + } catch (e) { + print(e); + return false; + } + } + + static Future deleteBPDetails(bmiId,customerId) async { + var uri = Uri.parse(deleteBPDetailsUrl + '/' + customerId+'/'+ bmiId); + + try { + var response = await http.delete(uri, headers: await buildRequestHeaders()); + + if (response.statusCode == 200) { + return true; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.delete(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return true; + } else { + return false; + } + } else { + return false; + } + } else { + return false; + } + } catch (e) { + print(e); + return false; + } + } + + static Future deleteSugarDetails(bmiId,customerId) async { + var uri = Uri.parse(deleteSugarDetailsUrl + '/' + customerId+'/'+ bmiId); + + try { + var response = await http.delete(uri, headers: await buildRequestHeaders()); + + if (response.statusCode == 200) { + return true; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.delete(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return true; + } else { + return false; + } + } else { + return false; + } + } else { + return false; + } + } catch (e) { + print(e); + return false; + } + } + + /*upload and update findings*/ + + static Future uploadFindingsGallery(file,customerId) async { + + var request = http.MultipartRequest( + 'POST', Uri.parse(findingsUploadPicUrl + '/' + customerId)); + if (file.length > 0) { + for (var i = 0; i < file.length; i++) { + request.files.add(await http.MultipartFile.fromPath('picture', file[i].path)); + }} + // request.files.add(await http.MultipartFile.fromPath('picture', images.toString().replaceAll('[', '').replaceAll(']',''))); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + static Future uploadFindingsCamera(file,customerId) async { + var request = http.MultipartRequest('POST', Uri.parse(findingsUploadPicUrl + '/' + customerId)); + request.files.add(await http.MultipartFile.fromPath('picture', file.path)); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + static Future addFindingsGallery(file,pictureId,customerId) async { + + var request = http.MultipartRequest( + 'PUT', Uri.parse(addFindingsUrl + '/' + customerId+"/"+pictureId)); + if (file.length > 0) { + for (var i = 0; i < file.length; i++) { + request.files.add(await http.MultipartFile.fromPath('picture', file[i].path)); + }} + // request.files.add(await http.MultipartFile.fromPath('picture', images.toString().replaceAll('[', '').replaceAll(']',''))); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + static Future addFindingsCamera(file,pictureId,customerId) async { + var request = http.MultipartRequest('PUT', Uri.parse(addFindingsUrl + '/' + customerId+"/"+pictureId)); + request.files.add(await http.MultipartFile.fromPath('picture', file.path)); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + static Future updateFindingsGallery(file,var recordId,customerId) async { + + var request = http.MultipartRequest( + 'POST', Uri.parse(updateFindingsUploadPicUrl + '/' + customerId+'/'+recordId)); + if (file.length > 0) { + for (var i = 0; i < file.length; i++) { + request.files.add(await http.MultipartFile.fromPath('picture', file[i].path)); + }} + // request.files.add(await http.MultipartFile.fromPath('picture', images.toString().replaceAll('[', '').replaceAll(']',''))); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + static Future updateFindingsCamera(file,var recordId,customerId) async { + var request = http.MultipartRequest('POST', Uri.parse(updateFindingsUploadPicUrl + '/' + customerId+'/'+recordId)); + request.files.add(await http.MultipartFile.fromPath('picture', file.path)); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + /*End*/ + + + /*upload and update Reports*/ + + static Future uploadReportsGallery(file,customerId) async { + + var request = http.MultipartRequest( + 'POST', Uri.parse(reportsUploadPicUrl + '/' + customerId)); + if (file.length > 0) { + for (var i = 0; i < file.length; i++) { + request.files.add(await http.MultipartFile.fromPath('picture', file[i].path)); + }} + // request.files.add(await http.MultipartFile.fromPath('picture', images.toString().replaceAll('[', '').replaceAll(']',''))); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + static Future uploadReportsCamera(file,customerId) async { + var request = http.MultipartRequest('POST', Uri.parse(reportsUploadPicUrl + '/' + customerId)); + request.files.add(await http.MultipartFile.fromPath('picture', file.path)); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + static Future addReportsGallery(file,pictureId,customerId) async { + + var request = http.MultipartRequest( + 'PUT', Uri.parse(addReportsUrl + '/' + customerId+"/"+pictureId)); + if (file.length > 0) { + for (var i = 0; i < file.length; i++) { + request.files.add(await http.MultipartFile.fromPath('picture', file[i].path)); + }} + // request.files.add(await http.MultipartFile.fromPath('picture', images.toString().replaceAll('[', '').replaceAll(']',''))); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + static Future addReportsCamera(file,pictureId,customerId) async { + var request = http.MultipartRequest('PUT', Uri.parse(addReportsUrl + '/' + customerId+"/"+pictureId)); + request.files.add(await http.MultipartFile.fromPath('picture', file.path)); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + static Future updateReportsGallery(file,var recordId,customerId) async { + + var request = http.MultipartRequest( + 'POST', Uri.parse(updateReportsUploadPicUrl + '/' + customerId+'/'+recordId)); + if (file.length > 0) { + for (var i = 0; i < file.length; i++) { + request.files.add(await http.MultipartFile.fromPath('picture', file[i].path)); + }} + // request.files.add(await http.MultipartFile.fromPath('picture', images.toString().replaceAll('[', '').replaceAll(']',''))); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + static Future updateReportsCamera(file,var recordId,customerId) async { + var request = http.MultipartRequest('POST', Uri.parse(updateReportsUploadPicUrl + '/' + customerId+'/'+recordId)); + request.files.add(await http.MultipartFile.fromPath('picture', file.path)); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + /*End*/ + + + /*upload and update Prescriptions*/ + + static Future uploadPrescriptionsGallery(file,customerId) async { + + var request = http.MultipartRequest( + 'POST', Uri.parse(prescriptionUploadPicUrl + '/' + customerId)); + if (file.length > 0) { + for (var i = 0; i < file.length; i++) { + request.files.add(await http.MultipartFile.fromPath('picture', file[i].path)); + }} + // request.files.add(await http.MultipartFile.fromPath('picture', images.toString().replaceAll('[', '').replaceAll(']',''))); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + static Future uploadPrescriptionsCamera(file,customerId) async { + var request = http.MultipartRequest('POST', Uri.parse(prescriptionUploadPicUrl + '/' + customerId)); + request.files.add(await http.MultipartFile.fromPath('picture', file.path)); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + static Future addPrescriptionsGallery(file,pictureId,customerId) async { + + var request = http.MultipartRequest( + 'PUT', Uri.parse(addPrescriptionsUrl + '/' + customerId+"/"+pictureId)); + if (file.length > 0) { + for (var i = 0; i < file.length; i++) { + request.files.add(await http.MultipartFile.fromPath('picture', file[i].path)); + }} + // request.files.add(await http.MultipartFile.fromPath('picture', images.toString().replaceAll('[', '').replaceAll(']',''))); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + static Future addPrescriptionsCamera(file,pictureId,customerId) async { + var request = http.MultipartRequest('PUT', Uri.parse(addPrescriptionsUrl + '/' + customerId+"/"+pictureId)); + request.files.add(await http.MultipartFile.fromPath('picture', file.path)); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + static Future updatePrescriptionsGallery(file,var recordId,customerId) async { + + var request = http.MultipartRequest( + 'POST', Uri.parse(updatePrescriptionPicUrl + '/' + customerId+'/'+recordId)); + if (file.length > 0) { + for (var i = 0; i < file.length; i++) { + request.files.add(await http.MultipartFile.fromPath('picture', file[i].path)); + }} + // request.files.add(await http.MultipartFile.fromPath('picture', images.toString().replaceAll('[', '').replaceAll(']',''))); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + static Future updatePrescriptionsCamera(file,var recordId,customerId) async { + var request = http.MultipartRequest('POST', Uri.parse(updatePrescriptionPicUrl + '/' + customerId+'/'+recordId)); + request.files.add(await http.MultipartFile.fromPath('picture', file.path)); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + /*End*/ + + static Future deleteRecordsNew(payload, recordId,customerId) async { + var uri = Uri.parse(deleteRecordsUrl + '/' + customerId+'/'+recordId); + + try { + var response = await http.post(uri, body: json.encode(payload),headers: await buildRequestHeaders()); + + if (response.statusCode == 200) { + return response.body; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.delete(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else { + return ''; + } + } else { + return ''; + } + } else { + return ''; + } + } catch (e) { + print(e); + return ''; + } + } + + static Future updateRecord(payload,recordId) async { + var uri = Uri.parse(updateRecordsUrl + '/' + recordId); + var response = await http.put(uri, + body: json.encode(payload), headers: await buildRequestHeaders()); + + if (response.statusCode == 200) { + try { + var _response = json.decode(response.body); + print(_response); + return true; + } catch (e) { + print(e); + return false; + } + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.put(uri, + body: json.encode(payload), headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return true; + } else { + return false; + } + } else { + return false; + } + } else { + return false; + } + } + + static Future deleteFindings(fileName,findingsId,customerId) async { + var uri = Uri.parse(deleteFindingsUrl + '/' + customerId+'/'+findingsId+'/'+fileName); + + try { + var response = await http.delete(uri, headers: await buildRequestHeaders()); + + if (response.statusCode == 200) { + return response.body; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.delete(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else { + return ''; + } + } else { + return ''; + } + } else { + return ''; + } + } catch (e) { + print(e); + return ''; + } + } + + static Future deletePrescriptions(fileName,prescriptionId,customerId) async { + var uri = Uri.parse(deletePrescriptionsUrl + '/' + customerId+'/'+prescriptionId+'/'+fileName); + + try { + var response = await http.delete(uri, headers: await buildRequestHeaders()); + + if (response.statusCode == 200) { + return response.body; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.delete(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else { + return ''; + } + } else { + return ''; + } + } else { + return ''; + } + } catch (e) { + print(e); + return ''; + } + } + + static Future deleteReports(fileName,reportsId,customerId) async { + var uri = Uri.parse(deleteReportsUrl + '/' + customerId+'/'+reportsId+'/'+fileName); + + try { + var response = await http.delete(uri, headers: await buildRequestHeaders()); + + if (response.statusCode == 200) { + return response.body; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.delete(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else { + return ''; + } + } else { + return ''; + } + } else { + return ''; + } + } catch (e) { + print(e); + return ''; + } + } + + static Future getAllConnectedDoctors(customerId) async { + var uri = Uri.parse(getAllConnectedDoctorsDataUrl + '/' + customerId); + //uri = uri.replace(query: 'customerId=$customerId'); + + var response = await http.get(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.get(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else { + return ''; + } + } else { + return ''; + } + } else { + return ''; + } + } + + static Future addRecords(payload,customerId) async { + var uri = Uri.parse(addRecordsUrl + '/' + customerId); + var response = await http.post(uri, + body: json.encode(payload), headers: await buildRequestHeaders()); + + if (response.statusCode == 200) { + try { + var _response = json.decode(response.body); + print(_response); + return true; + } catch (e) { + print(e); + return false; + } + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.post(uri, + body: json.encode(payload), headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return true; + } else { + return false; + } + } else { + return false; + } + } else { + return false; + } + } + + static Future uploadImageHTTPForPrescriptions(file,customerId) async { + var request = http.MultipartRequest( + 'POST', Uri.parse(prescriptionUploadPicUrl + '/' + customerId)); + request.files.add(await http.MultipartFile.fromPath('picture', file.path)); + var res = await request.send(); + var response = await http.Response.fromStream(res); + return response.body; + } + + static Future addPrescription(payload,customerId) async { + var uri = Uri.parse(addPrescriptionUrl + '/' + customerId); + var response = await http.post(uri, + body: json.encode(payload), headers: await buildRequestHeaders()); + + if (response.statusCode == 200) { + try { + var _response = json.decode(response.body); + print(_response); + return true; + } catch (e) { + print(e); + return false; + } + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.post(uri, + body: json.encode(payload), headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return true; + } else { + return false; + } + } else { + return false; + } + } else { + return false; + } + } + + static Future getAllReportProblemDetalis(customerId) async { + var uri = Uri.parse(getAllReportProblemDetalisUrl+'/'+customerId); + //uri = uri.replace(query: 'customerId=$customerId'); + + var response = await http.get(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else if (response.statusCode == 401) { + bool status = await AppSettings.resetToken(); + if (status) { + response = await http.get(uri, headers: await buildRequestHeaders()); + if (response.statusCode == 200) { + return response.body; + } else { + return ''; + } + } else { + return ''; + } + } else { + return ''; + } + } + /*Apis ends here*/ diff --git a/lib/models/all_problems_model.dart b/lib/models/all_problems_model.dart new file mode 100644 index 0000000..0904ca3 --- /dev/null +++ b/lib/models/all_problems_model.dart @@ -0,0 +1,33 @@ +import 'package:intl/intl.dart'; + +class AllProblemsModel { + String problem=''; + String audio=''; + String description=''; + String video=''; + String date=''; + String problemId=''; + List picture = []; + String image=''; + bool isAudioButtonEnabled=false; + DateTime dateForFilter=new DateTime.now(); + String dateNew=''; + + AllProblemsModel(); + + factory AllProblemsModel.fromJson(Map json){ + AllProblemsModel rtvm = new AllProblemsModel(); + + rtvm.problem = json['name'] ?? ''; + rtvm.audio = json['audio'] ?? ''; + rtvm.description = json['description'] ?? ''; + rtvm.video = json['video'] ?? ''; + rtvm.date = json['date'] ?? ''; + rtvm.dateForFilter = DateFormat('dd-MM-yyyy').parse(rtvm.date); + rtvm.problemId = json['reportId'] ?? ''; + rtvm.picture = json['picture'] ?? []; + rtvm.image=json['picture'][0]['url']??''; + return rtvm; + } + +} \ No newline at end of file diff --git a/lib/models/bmi_history_model.dart b/lib/models/bmi_history_model.dart new file mode 100644 index 0000000..4a51b2a --- /dev/null +++ b/lib/models/bmi_history_model.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:intl/intl.dart'; + + +class BmiHistoryModel { + String bmiValue = ''; + String height= ''; + String weight= ''; + String date= ''; + String actualDate= ''; + String displayDate=''; + DateTime dateForFilter=new DateTime.now(); + String bmiInfoId = ''; + String bmiText = ''; + Color bmiTextColor = Colors.black; + var number1; + var number2; + + BmiHistoryModel(); + + factory BmiHistoryModel.fromJson(Map json){ + BmiHistoryModel rtvm = new BmiHistoryModel(); + + rtvm.bmiValue = json['bmivalue'].toString() ?? ''; + rtvm.bmiInfoId = json['bmiinfoid'].toString() ?? ''; + rtvm.height = json['height'].toString() ?? ''; + rtvm.weight = json['weight'].toString() ?? ''; + rtvm.number1 = double.parse( rtvm.bmiValue); + rtvm.number2 = double.parse( rtvm.bmiValue); + rtvm.date = json['createdAt'].toString() ?? ''; + rtvm.actualDate = json['date'].toString() ?? ''; + rtvm.dateForFilter = DateFormat('dd-MM-yyyy').parse(rtvm.actualDate); + if(double.parse(rtvm.bmiValue)<18.5){ + rtvm.bmiText='Underweight'; + rtvm.bmiTextColor=Colors.red; + } + else if(double.parse(rtvm.bmiValue)>=18.5&&double.parse(rtvm.bmiValue)<=24.9){ + rtvm.bmiText='Normal weight'; + rtvm.bmiTextColor=buttonColors; + } + else if(double.parse(rtvm.bmiValue)>=25&&double.parse(rtvm.bmiValue)<=29.9){ + rtvm.bmiText='Overweight'; + rtvm.bmiTextColor=Colors.red; + } + else if(double.parse(rtvm.bmiValue)>=30){ + rtvm.bmiText='Obesity'; + rtvm.bmiTextColor=Colors.red; + } + + + return rtvm; + } + +} \ No newline at end of file diff --git a/lib/models/bp_history_model.dart b/lib/models/bp_history_model.dart new file mode 100644 index 0000000..49ab801 --- /dev/null +++ b/lib/models/bp_history_model.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; + + +class BPHistoryModel { + String bpText = ''; + String systolic= ''; + String diastolic= ''; + String date= ''; + String bpId= ''; + String displayDate=''; + String actualDate=''; + DateTime dateForFilter=new DateTime.now(); + + + BPHistoryModel(); + + factory BPHistoryModel.fromJson(Map json){ + BPHistoryModel rtvm = new BPHistoryModel(); + + rtvm.bpText = json['bpCategory'].toString() ?? ''; + rtvm.systolic = json['Systolic'].toString() ?? ''; + rtvm.diastolic = json['Diastolic'].toString() ?? ''; + rtvm.date = json['createdAt'].toString() ?? ''; + rtvm.actualDate = json['date'].toString() ?? ''; + rtvm.bpId= json['bpinfoid'].toString() ?? ''; + + rtvm.dateForFilter = DateFormat('dd-MM-yyyy').parse(rtvm.actualDate); + + + return rtvm; + } + +} \ No newline at end of file diff --git a/lib/models/get_connected_doctors_model.dart b/lib/models/get_connected_doctors_model.dart new file mode 100644 index 0000000..53d6ea1 --- /dev/null +++ b/lib/models/get_connected_doctors_model.dart @@ -0,0 +1,30 @@ + + +class GetConnectedDoctorsModel { + String doctor_name=''; + String doctor_id=''; + String specialization=''; + String qualification=''; + String practiceplace1=''; + String practiceplace2=''; + String practiceplace3=''; + String hospital_name=''; + + + + + + GetConnectedDoctorsModel(); + + factory GetConnectedDoctorsModel.fromJson(Map json){ + GetConnectedDoctorsModel rtvm = new GetConnectedDoctorsModel(); + rtvm.doctor_name = json['doctorName'] ?? ''; + rtvm.specialization = json['specialization'] ?? ''; + rtvm.qualification = json['qualification'] ?? ''; + rtvm.doctor_id = json['doctorId'] ?? ''; + rtvm.hospital_name = json['placeOfPractice'][0]['hospitalName'] ?? ''; + + return rtvm; + } + +} \ No newline at end of file diff --git a/lib/models/prescriptions_model.dart b/lib/models/prescriptions_model.dart new file mode 100644 index 0000000..651e5c7 --- /dev/null +++ b/lib/models/prescriptions_model.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:doctor/common/settings.dart'; + +class PrescriptionsModel { + String prescription_name = ''; + String patient_name=''; + String prescription_url=''; + String age=''; + String gender=''; + String patient_type=''; + List prescriptionUrls=[]; + + + PrescriptionsModel(); + + factory PrescriptionsModel.fromJson(Map json){ + PrescriptionsModel rtvm = new PrescriptionsModel(); + + rtvm.prescriptionUrls=json['precription']??[]; + + /*rtvm.prescription_name = json['name'] ?? ''; + rtvm.patient_type = json['patientType'] ?? ''; + rtvm.prescription_url = json['pictureUrl'][0] ?? ''; + + if(rtvm.patient_type.toString().toLowerCase()=='self'){ + rtvm.age=AppSettings.age; + rtvm.gender=AppSettings.gender; + rtvm.patient_name=AppSettings.userName; + } + + else{ + rtvm.age=json['others']['age'].toString(); + rtvm.gender=json['others']['gender']; + rtvm.patient_name=json['others']['name']; + }*/ + + return rtvm; + } + +} \ No newline at end of file diff --git a/lib/models/reports_model.dart b/lib/models/reports_model.dart new file mode 100644 index 0000000..c379b30 --- /dev/null +++ b/lib/models/reports_model.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:intl/intl.dart'; + +class ReportsModel { + String patient_name=''; + String age=''; + String gender=''; + String patient_type=''; + String problem=''; + String doctorName=''; + String hospitalName=''; + String date=''; + String recordId=''; + List findingsImages = []; + List reportImages = []; + List prescriptionImages = []; + DateTime dateForFilter=new DateTime.now(); + + ReportsModel(); + + factory ReportsModel.fromJson(Map json){ + ReportsModel rtvm = new ReportsModel(); + + rtvm.patient_type = json['patientType'] ?? ''; + rtvm.doctorName = json['doctorName'] ?? ''; + rtvm.hospitalName = json['hospitalName'] ?? ''; + rtvm.problem = json['problem'] ?? ''; + rtvm.date = json['date'] ?? ''; + rtvm.recordId = json['recordId'] ?? ''; + rtvm.findingsImages = json['findings'] ?? []; + rtvm.reportImages = json['reports'] ?? []; + rtvm.prescriptionImages = json['prescription'] ?? []; + rtvm.dateForFilter = DateFormat('dd-MM-yyyy').parse(rtvm.date); + + if(rtvm.patient_type.toString().toLowerCase()!='self'){ + rtvm.age=json['others']['age'].toString(); + rtvm.gender=json['others']['gender']; + rtvm.patient_name=json['others']['name']; + } + + return rtvm; + } + +} \ No newline at end of file diff --git a/lib/models/sugar_history_model.dart b/lib/models/sugar_history_model.dart new file mode 100644 index 0000000..ea09a4a --- /dev/null +++ b/lib/models/sugar_history_model.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:intl/intl.dart'; + + +class SugarHistoryModel { + String sugartText = ''; + String sugarValue = ''; + String fasting= ''; + String postPrandial= ''; + String date= ''; + String displayDate=''; + String actualDate=''; + String sugarInfoId=''; + DateTime dateForFilter=new DateTime.now(); + Color sugarValueColor=Colors.black; + + + SugarHistoryModel(); + + factory SugarHistoryModel.fromJson(Map json){ + SugarHistoryModel rtvm = new SugarHistoryModel(); + + + rtvm.sugartText = json['sugarCategory'].toString() ?? ''; + rtvm.sugarValue = json['sugarValue'].toString() ?? ''; + rtvm.fasting = json['fasting'].toString() ?? ''; + rtvm.postPrandial = json['postPrandial'].toString() ?? ''; + rtvm.date = json['createdAt'].toString() ?? ''; + rtvm.actualDate = json['date'].toString() ?? ''; + rtvm.sugarInfoId = json['sugarinfoid'].toString() ?? ''; + + if(rtvm.sugartText.toUpperCase().toUpperCase()=='VERY HIGH BLOOD SUGAR'){ + rtvm.sugarValueColor=Colors.red; + } + else if(rtvm.sugartText.toUpperCase().toUpperCase()=='HIGH BLOOD SUGAR'){ + rtvm.sugarValueColor=Colors.red; + } + else if(rtvm.sugartText.toUpperCase().toUpperCase()=='PREDIABETES (IMPAIRED FASTING GLUCOSE)'){ + rtvm.sugarValueColor=Colors.red; + } + else if(rtvm.sugartText.toUpperCase().toUpperCase()=='VERY LOW BLOOD SUGAR'){ + rtvm.sugarValueColor=Colors.red; + } + else if(rtvm.sugartText.toUpperCase().toUpperCase()=='LOW BLOOD SUGAR'){ + rtvm.sugarValueColor=Colors.red; + } + else if(rtvm.sugartText.toUpperCase().toUpperCase()=='NORMAL BLOOD SUGAR (HEALTHY RANGE)'){ + rtvm.sugarValueColor=buttonColors; + } + else{ + rtvm.sugarValueColor=Colors.black; + } + + //DateTime tempDate = new DateFormat("yyyy-MM-dd hh:mm:ss").parse(rtvm.date); + rtvm.dateForFilter = DateFormat('dd-MM-yyyy').parse(rtvm.actualDate); + + + return rtvm; + } + +} \ No newline at end of file diff --git a/lib/patient_dashboard/BMI/bmi_caluculator.dart b/lib/patient_dashboard/BMI/bmi_caluculator.dart new file mode 100644 index 0000000..f659026 --- /dev/null +++ b/lib/patient_dashboard/BMI/bmi_caluculator.dart @@ -0,0 +1,539 @@ +import 'dart:convert'; +import 'package:intl/intl.dart'; +import 'package:flutter/material.dart'; +import 'package:doctor/patient_dashboard/BMI/bmi_history.dart'; +import 'package:doctor/common/settings.dart'; + +class BMICalculator extends StatefulWidget { + String? customerId; + BMICalculator({this.customerId}); + + @override + State createState() => _BMICalculatorState(); +} + +class _BMICalculatorState extends State { + TextEditingController heightController = TextEditingController(); + TextEditingController inchesController = TextEditingController(); + TextEditingController cmsController = TextEditingController(); + TextEditingController weightController = TextEditingController(); + TextEditingController ageController = TextEditingController(); + TextEditingController dateInput = TextEditingController(); + + String bmiValue = ''; + String bmiText = ''; + Color bmiTextColor = Colors.black; + var heightUnitItems = [ + 'feet', + 'cm', + ]; + var heightUnits = 'feet'; + var weightUnitItems = [ + 'kg', + ]; + var weightUnits = 'kg'; + + @override + void initState() { + ageController.text = AppSettings.age; + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppSettings.appBar('Calculate BMI'), + body: SingleChildScrollView( + child: Container( + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + TextFormField( + cursorColor: greyColor, + controller: ageController, + textCapitalization: TextCapitalization.characters, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.person, + color: primaryColor, + ), + suffixText: "Yrs", + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + labelText: 'Age', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + SizedBox(height: 10), + DropdownButtonFormField( + // Initial Value + value: heightUnits, + isExpanded: true, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.ac_unit_outlined, + color: primaryColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + labelText: 'Select Height units', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + + hint: Text('Units'), + // Down Arrow Icon + //icon: const Icon(Icons.keyboard_arrow_down), + + // Array list of items + items: heightUnitItems.map((String items) { + return DropdownMenuItem( + value: items, + child: Text( + items, + style: TextStyle( + fontSize: 16, + ), + textAlign: TextAlign.center, + )); + }).toList(), + // After selecting the desired option,it will + // change button value to selected value + onChanged: (String? newValue) { + setState(() { + heightUnits = newValue!; + }); + }, + ), + SizedBox(height: 10), + Visibility( + visible: heightUnits == 'feet', + child: Container( + //height: 60, + child: Row( + children: [ + Expanded( + child: TextFormField( + cursorColor: greyColor, + controller: heightController, + textCapitalization: TextCapitalization.characters, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.height, + color: primaryColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + labelText: 'Feets', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + ), + SizedBox(width: 5), + Expanded( + child: TextFormField( + cursorColor: greyColor, + controller: inchesController, + textCapitalization: TextCapitalization.characters, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.height, + color: primaryColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + labelText: 'Inches', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + ), + SizedBox(width: 5), + ], + ), + ), + ), + Visibility( + visible: heightUnits == 'cm', + child: Container( + //height: 60, + child: Row( + children: [ + Expanded( + child: TextFormField( + cursorColor: greyColor, + controller: cmsController, + textCapitalization: TextCapitalization.characters, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.height, + color: primaryColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + labelText: 'Enter height in cms', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + ), + ], + ), + ), + ), + SizedBox(height: 10), + Container( + //height: 40, + padding: const EdgeInsets.fromLTRB(0, 0, 0, 0), + child: Row( + children: [ + Expanded( + child: TextFormField( + cursorColor: greyColor, + controller: weightController, + textCapitalization: TextCapitalization.characters, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.line_weight_outlined, + color: primaryColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + labelText: 'Weight', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + ), + SizedBox(width: 5), + Expanded( + child: DropdownButtonFormField( + // Initial Value + value: weightUnits, + isExpanded: true, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.ac_unit_outlined, + color: primaryColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + labelText: 'Units', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + + hint: Text('Units'), + // Down Arrow Icon + //icon: const Icon(Icons.keyboard_arrow_down), + + // Array list of items + items: weightUnitItems.map((String items) { + return DropdownMenuItem( + value: items, + child: Text( + items, + style: TextStyle( + fontSize: 16, + ), + textAlign: TextAlign.center, + )); + }).toList(), + // After selecting the desired option,it will + // change button value to selected value + onChanged: (String? newValue) { + setState(() { + weightUnits = newValue!; + }); + }, + ), + ) + ], + ), + ), + SizedBox(height: 10), + Container( + child: TextFormField( + cursorColor: greyColor, + controller: dateInput, + decoration: textFormFieldDecorationBMI( + Icons.calendar_today, 'Enter Date'), + readOnly: true, + onTap: () async { + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1950), + lastDate: DateTime.now(), + builder: (BuildContext context, Widget? child) { + return Theme( + data: ThemeData.dark().copyWith( + colorScheme: ColorScheme.dark( + primary: buttonColors, + onPrimary: Colors.white, + surface: buttonColors, + onSurface: Colors.white, + ), + dialogBackgroundColor: primaryColor, + ), + child: child!, + ); + }, + ); + + if (pickedDate != null) { + print( + pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000 + String formattedDate = + DateFormat('dd-MM-yyyy').format(pickedDate); + print( + formattedDate); //formatted date output using intl package => 2021-03-16 + setState(() { + dateInput.text = + formattedDate; //set output date to TextField value. + }); + } else {} + }, + ), + ), + SizedBox(height: 10), + Container( + width: double.infinity, + height: MediaQuery.of(context).size.height * .05, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: buttonColors, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () async { + if (ageController.text != '' && + heightController.text != '' || + cmsController.text != '' && + weightController.text != '' && + dateInput.text != '') { + if (int.parse(heightController.text) > 7) { + AppSettings.longFailedToast( + 'Please enter feet below 8 feets'); + } else if (int.parse(inchesController.text) > 12) { + AppSettings.longFailedToast( + 'Please enter inches below 12'); + } else if (int.parse(heightController.text) == 0 && + int.parse(inchesController.text) < 6) { + AppSettings.longFailedToast( + 'Please enter inches above 6'); + } else { + AppSettings.preLoaderDialog(context); + var payload = new Map(); + + if (heightUnits.toString().toLowerCase() == + 'feet') { + cmsController.text = ''; + } else { + heightController.text = ''; + inchesController.text = ''; + } + + payload["age"] = + int.parse(ageController.text.toString()); + payload["feet"] = heightController.text.toString(); + payload["inches"] = + inchesController.text.toString(); + payload["height"] = cmsController.text.toString(); + payload["weight"] = + weightController.text.toString(); + payload["heightUnit"] = heightUnits.toString(); + payload["weightUnit"] = weightUnits.toString(); + payload["date"] = dateInput.text.toString(); + + try { + var value = + await AppSettings.calculateBmi(payload,widget.customerId); + var valueResponse = jsonDecode(value); + Navigator.of(context, rootNavigator: true).pop(); + heightController.clear(); + cmsController.clear(); + inchesController.clear(); + weightController.clear(); + dateInput.clear(); + setState(() { + bmiValue = valueResponse['userDetails'] + ['bmivalue'] + .toString(); + if (double.parse(bmiValue) < 18.5) { + bmiText = 'Underweight'; + bmiTextColor=Colors.red; + } else if (double.parse(bmiValue) >= 18.5 && + double.parse(bmiValue) <= 24.9) { + bmiText = 'Normal weight'; + bmiTextColor=buttonColors; + } else if (double.parse(bmiValue) >= 25 && + double.parse(bmiValue) <= 29.9) { + bmiText = 'Overweight'; + bmiTextColor=Colors.red; + } else if (double.parse(bmiValue) >= 30) { + bmiText = 'Obesity'; + bmiTextColor=Colors.red; + } + }); + } catch (e) { + Navigator.of(context, rootNavigator: true).pop(); + AppSettings.longFailedToast( + 'Calculating BMI failed'); + } + } + } else { + AppSettings.longFailedToast( + 'Please enter valid details'); + } + }, + child: const Text('Calculate BMI'), + )), + SizedBox(height: 20), + Container( + child: Row( + children: [ + Text( + 'Your BMI value: $bmiValue', + style: + TextStyle(fontSize: 15, fontWeight: FontWeight.bold), + ), + SizedBox( + width: 10, + ), + Text(bmiText, + style: TextStyle( + color: bmiTextColor, fontWeight: FontWeight.bold,fontSize: 20)), + ], + )), + SizedBox(height: 30), + Container( + child: Text( + 'Underweight = <18.5', + style: bmiTextStyle(), + ), + ), + SizedBox(height: 10), + Container( + child: + Text('Normal weight = 18.5–24.9', style: bmiTextStyle()), + ), + SizedBox(height: 10), + Container( + child: Text('Overweight = 25–29.9', style: bmiTextStyle()), + ), + SizedBox(height: 10), + Container( + child: Text('Obesity = BMI of 30 or greater', + style: bmiTextStyle()), + ), + SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + children: [ + IconButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => BMIHistory(customerId: widget.customerId,)), + ); + }, + icon: Icon( + Icons.history, + color: primaryColor, + size: 40, + ), + ), + SizedBox(height: 10), + Padding( + padding: EdgeInsets.fromLTRB(10, 0, 0, 0), + child: Container( + child: Text('History', + style: TextStyle( + color: Colors.black, + fontSize: 12, + fontWeight: FontWeight.bold, + )), + ), + ) + ], + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + primary: buttonColors, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () async { + Navigator.pop(context); + }, + child: const Text('Cancel'), + ) + ], + ) + ], + ), + )), + )); + } +} diff --git a/lib/patient_dashboard/BMI/bmi_history.dart b/lib/patient_dashboard/BMI/bmi_history.dart new file mode 100644 index 0000000..ff8d882 --- /dev/null +++ b/lib/patient_dashboard/BMI/bmi_history.dart @@ -0,0 +1,424 @@ +import 'dart:convert'; +import 'package:doctor/patient_dashboard/BMI/bmi_caluculator.dart'; +import 'package:flutter/material.dart'; +import 'package:doctor/models/bmi_history_model.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; + +class BMIHistory extends StatefulWidget { + String? customerId; + BMIHistory({this.customerId}); + + + @override + State createState() => _BMIHistoryState(); +} + +class _BMIHistoryState extends State { + bool isLoading = false; + List bmiHistoryList = []; + List FilteredList = []; + var dateItems = [ + 'All', + 'last 7 days', + 'last one month', + 'last one year', + ]; + var dateItemsVariable = 'All'; + + Future getBmiHistoryDetails(var selectedRange) async { + isLoading = true; + var response1 = await AppSettings.getBmiHistory(widget.customerId); + print(response1); + setState(() { + bmiHistoryList = ((jsonDecode(response1)) as List).map((dynamic model) { + return BmiHistoryModel.fromJson(model); + }).toList(); + + var now = new DateTime.now(); + var now_1w = now.subtract(Duration(days: 7)); + var now_1m = new DateTime(now.year, now.month - 1, now.day); + var now_1y = new DateTime(now.year - 1, now.month, now.day); + + if (selectedRange.toString().toUpperCase() == 'LAST 7 DAYS') { + FilteredList = bmiHistoryList.where((product) { + final date = product.dateForFilter; + return now_1w.isBefore(date); + //reportsList=reportsListOriginal.reversed.toList(); + }).toList(); + } + else if (selectedRange.toString().toUpperCase() == 'LAST ONE MONTH') { + FilteredList = bmiHistoryList.where((product) { + final date = product.dateForFilter; + return now_1m.isBefore(date); + }).toList(); + } + else if (selectedRange.toString().toUpperCase() == 'LAST ONE YEAR') { + FilteredList = bmiHistoryList.where((product) { + final date = product.dateForFilter; + return now_1y.isBefore(date); + }).toList(); + } + else { + FilteredList = bmiHistoryList; + } + + isLoading = false; + }); + } + + @override + void initState() { + getBmiHistoryDetails(dateItemsVariable); + super.initState(); + } + + deleteBmiHistory(bmiId) async{ + + AppSettings.preLoaderDialog(context); + bool status = await AppSettings.deleteBMIDetails(bmiId,widget.customerId); + + if(status){ + Navigator.of(context, rootNavigator: true).pop(); + + AppSettings.longSuccessToast("BMI record deleted successfully"); + await getBmiHistoryDetails(dateItemsVariable); + } + else{ + Navigator.of(context, rootNavigator: true).pop(); + + AppSettings.longFailedToast("BMI record deletion failed"); + } + + + + } + + Widget renderzUi() { + if (FilteredList.length != 0) { + FilteredList.sort((a, b) => a.actualDate.compareTo(b.actualDate)); + return Column(crossAxisAlignment: CrossAxisAlignment.end, children: [ + Padding( + padding: EdgeInsets.fromLTRB(10, 10, 10, 10), + child: DropdownButtonFormField( + // Initial Value + value: dateItemsVariable, + isExpanded: true, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.calendar_month, + color: primaryColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + labelText: 'Select Date Range', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + + hint: Text('Units'), + // Down Arrow Icon + //icon: const Icon(Icons.keyboard_arrow_down), + + // Array list of items + items: dateItems.map((String items) { + return DropdownMenuItem( + value: items, + child: Text( + items, + style: TextStyle( + fontSize: 16, + ), + textAlign: TextAlign.center, + )); + }).toList(), + // After selecting the desired option,it will + // change button value to selected value + onChanged: (String? newValue) { + setState(() { + dateItemsVariable = newValue!; + }); + getBmiHistoryDetails(dateItemsVariable); + }, + ), + ), + IconButton( + onPressed: () { + /*Navigator.push( + context, + MaterialPageRoute( + builder: (context) => BmiChart()), + );*/ + /*Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new BmiChart(myObject: FilteredList)));*/ + // showBMIAdddialog(); + }, + icon: Icon( + Icons.auto_graph, + color: primaryColor, + ), + ), + Expanded( + child: ListView.builder( + padding: EdgeInsets.all(0), + itemCount: FilteredList.length, + itemBuilder: (BuildContext context, int index) { + return Slidable( + key: const ValueKey(0), + endActionPane: ActionPane( + // A motion is a widget used to control how the pane animates. + motion: ScrollMotion(), + + dragDismissible: false, + // A pane can dismiss the Slidable. + dismissible: DismissiblePane(onDismissed: () { + deleteBmiHistory(FilteredList[index].bmiInfoId); + }), + + // All actions are defined in the children parameter. + children: [ + // A SlidableAction can have an icon and/or a label. + SlidableAction( + backgroundColor: Color(0xFFFE4A49), + foregroundColor: Colors.white, + icon: Icons.delete, + label: 'Delete', + onPressed: (BuildContext context) { + deleteBmiHistory(FilteredList[index].bmiInfoId); + }, + ), + /*SlidableAction( + onPressed: doNothing, + backgroundColor: Color(0xFF21B7CA), + foregroundColor: Colors.white, + icon: Icons.share, + label: 'Share', + ),*/ + ], + ), + child: Card( + color: Colors.white, + child: Padding( + padding: EdgeInsets.all(8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: MediaQuery.of(context).size.width * .55, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image( + image: const AssetImage( + 'images/height.png'), + height: 25, + width: 25, + fit: BoxFit.fill), + Padding( + padding: EdgeInsets.all(5), + child: Text( + FilteredList[index] + .height + .toString() + .toUpperCase() + + ' cms', + style: valuesTextStyle()), + ) + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image( + image: const AssetImage( + 'images/weight.png'), + height: 25, + width: 25, + fit: BoxFit.fill), + Padding( + padding: EdgeInsets.all(5), + child: Text( + FilteredList[index] + .weight + .toString() + .toUpperCase() + + ' Kgs', + style: valuesTextStyle()), + ) + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image( + image: + const AssetImage('images/date.png'), + height: 25, + width: 25, + fit: BoxFit.fill), + Padding( + padding: EdgeInsets.all(5), + child: Text( + FilteredList[index] + .actualDate + .toString() + .toUpperCase(), + style: valuesTextStyle()), + ) + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image( + image: const AssetImage( + 'images/bmi.png'), + height: 25, + width: 25, + fit: BoxFit.fill), + Padding( + padding: EdgeInsets.all(5), + child: Text( + FilteredList[index] + .bmiValue + .toString() + .toUpperCase(), + style: valuesTextStyle()), + ) + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image( + image: const AssetImage( + 'images/bmi.png'), + height: 25, + width: 25, + fit: BoxFit.fill), + Padding( + padding: EdgeInsets.all(5), + child: Text( + FilteredList[index].bmiText + .toString() + .toUpperCase(), + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold,color: FilteredList[index].bmiTextColor + )), + ) + ], + ), + ], + ), + ), + ], + ), + ), + ), + ); + + })), + ]); + } + else { + return Center( + child: Padding( + padding: EdgeInsets.fromLTRB(0, 40, 0, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + height: MediaQuery.of(context).size.height * .25, + ), + Text('No Data'), + SizedBox( + height: 20, + ), + CircleAvatar( + backgroundColor: primaryColor, + radius: 40, + child: IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.white, + ), + onPressed: () async { + Navigator.push(context, MaterialPageRoute(builder: (context) => BMICalculator(customerId:widget.customerId))).then((value) { + getBmiHistoryDetails(dateItemsVariable); + }); + }, + ), + ) + ], + ), + )); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppSettings.appBar('Body Mass Index'), + body: isLoading + ? Center( + child: CircularProgressIndicator( + color: primaryColor, + strokeWidth: 5.0, + ), + ) + : renderzUi(), + floatingActionButton: Visibility( + visible:FilteredList.length!=0, + child: CircleAvatar( + backgroundColor: buttonColors, + radius: 40, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.black, + ), + onPressed: () async { + Navigator.push(context, MaterialPageRoute(builder: (context) => BMICalculator(customerId: widget.customerId,))).then((value) { + getBmiHistoryDetails(dateItemsVariable); + }); + }, + ), + /* Padding( + padding: EdgeInsets.fromLTRB(5, 0, 5, 5), + child: Text( + 'Add Tanks ', + style: TextStyle(color: Colors.white), + ), + )*/ + ], + ), + ), + ), + ); + } +} diff --git a/lib/patient_dashboard/BP/bp_calculator.dart b/lib/patient_dashboard/BP/bp_calculator.dart new file mode 100644 index 0000000..1807ed4 --- /dev/null +++ b/lib/patient_dashboard/BP/bp_calculator.dart @@ -0,0 +1,228 @@ +import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:doctor/patient_dashboard/BP/bp_history.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:intl/intl.dart'; + +class BPCalculator extends StatefulWidget { + String? customerId; + BPCalculator({this.customerId}); + + @override + State createState() => _BPCalculatorState(); +} + +class _BPCalculatorState extends State { + + TextEditingController systoloicController = TextEditingController(); + TextEditingController diastolicController = TextEditingController(); + TextEditingController dateInput = TextEditingController(); + String bpValue = ''; + String bpText = ''; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppSettings.appBar('Blood Pressure'), + body: SingleChildScrollView( + child: Container( + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + TextFormField( + cursorColor: greyColor, + controller: systoloicController, + textCapitalization: TextCapitalization.characters, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.upload, + color: primaryColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + labelText: 'Enter systolic value', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + SizedBox(height: 10), + TextFormField( + cursorColor: greyColor, + controller: diastolicController, + textCapitalization: TextCapitalization.characters, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.download, + color: primaryColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + labelText: 'Enter diastolic value', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + SizedBox(height: 10), + Container( + child: TextFormField( + cursorColor: greyColor, + controller: dateInput, + decoration: textFormFieldDecorationBMI( + Icons.calendar_today, 'Enter Date'), + readOnly: true, + onTap: () async { + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1950), + lastDate: DateTime.now(), + builder: (BuildContext context, Widget? child) { + return Theme( + data: ThemeData.dark().copyWith( + colorScheme: ColorScheme.dark( + primary: buttonColors, + onPrimary: Colors.white, + surface: buttonColors, + onSurface: Colors.white, + ), + dialogBackgroundColor: primaryColor, + ), + child: child!, + ); + }, + ); + + if (pickedDate != null) { + print( + pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000 + String formattedDate = + DateFormat('dd-MM-yyyy').format(pickedDate); + print( + formattedDate); //formatted date output using intl package => 2021-03-16 + setState(() { + dateInput.text = + formattedDate; //set output date to TextField value. + }); + } else {} + }, + ), + ), + SizedBox(height: 10), + Container( + width: double.infinity, + height: + MediaQuery.of(context).size.height * .05, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: buttonColors, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () async { + if (systoloicController.text != '' && + diastolicController.text != ''&&dateInput.text!='') { + + if(int.parse(systoloicController.text)>int.parse(diastolicController.text)){ + AppSettings.preLoaderDialog(context); + var payload = new Map(); + + payload["Systolic"] = double.parse(systoloicController.text.toString()); + payload["Diastolic"] = double.parse(diastolicController.text.toString()); + payload["date"] =dateInput.text.toString(); + + var value = await AppSettings.calculateBP(payload,widget.customerId); + var valueResponse = jsonDecode(value); + print(valueResponse); + setState(() { + bpValue = valueResponse['userDetails']['bpCategory'].toString(); + }); + systoloicController.clear(); + diastolicController.clear(); + dateInput.clear(); + Navigator.of(context,rootNavigator: true).pop(); + } + else{ + AppSettings.longFailedToast('Please enter diastolic value less than systolic value'); + } + } + else{ + AppSettings.longFailedToast('Please enter valid details'); + } + }, + child: const Text('Check BP'), + )), + SizedBox(height: 20), + Container( + child: Row( + children: [ + Text(bpValue,style: TextStyle(color: Colors.red,fontWeight: FontWeight.bold,fontSize: 15),), + ], + ) + ), + SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + children: [ + IconButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => BPHistory(customerId: widget.customerId,)), + ); + }, + icon: Icon( + Icons.history, + color: primaryColor, + size: 40, + ), + ), + SizedBox(height: 10), + Padding(padding: EdgeInsets.fromLTRB(10,0,0,0), + child: Container( + child: Text('History',style:TextStyle(color:Colors.black,fontSize: 12,fontWeight: FontWeight.bold,)), + ),) + ], + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + primary: buttonColors, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () async { + Navigator.pop(context); + }, + child: const Text('Cancel'), + ) + ], + ) + + + ], + ), + ) + ), + ) + ); + } +} diff --git a/lib/patient_dashboard/BP/bp_history.dart b/lib/patient_dashboard/BP/bp_history.dart new file mode 100644 index 0000000..d7d76ed --- /dev/null +++ b/lib/patient_dashboard/BP/bp_history.dart @@ -0,0 +1,372 @@ +import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:doctor/patient_dashboard/BP/bp_calculator.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:doctor/models/bp_history_model.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; + +class BPHistory extends StatefulWidget { + String? customerId; + BPHistory({this.customerId}); + + @override + State createState() => _BPHistoryState(); +} + +class _BPHistoryState extends State { + bool isLoading = false; + List BpHistoryList = []; + List FilteredList = []; + var dateItems = [ + 'All', + 'last 7 days', + 'last one month', + 'last one year', + ]; + var dateItemsVariable = 'All'; + + Future getBPHistoryDetails(var selectedRange) async { + isLoading = true; + var response1 = await AppSettings.getBPHistory(widget.customerId); + print(response1); + setState(() { + BpHistoryList = ((jsonDecode(response1)) as List).map((dynamic model) { + return BPHistoryModel.fromJson(model); + }).toList(); + + var now = new DateTime.now(); + var now_1w = now.subtract(Duration(days: 7)); + var now_1m = new DateTime(now.year, now.month - 1, now.day); + var now_1y = new DateTime(now.year - 1, now.month, now.day); + + if (selectedRange.toString().toUpperCase() == 'LAST 7 DAYS') { + FilteredList = BpHistoryList.where((product) { + final date = product.dateForFilter; + return now_1w.isBefore(date); + }).toList(); + } else if (selectedRange.toString().toUpperCase() == 'LAST ONE MONTH') { + FilteredList = BpHistoryList.where((product) { + final date = product.dateForFilter; + return now_1m.isBefore(date); + }).toList(); + } else if (selectedRange.toString().toUpperCase() == 'LAST ONE YEAR') { + FilteredList = BpHistoryList.where((product) { + final date = product.dateForFilter; + return now_1y.isBefore(date); + }).toList(); + } else { + FilteredList = BpHistoryList; + } + + isLoading = false; + }); + } + + @override + void initState() { + getBPHistoryDetails(dateItemsVariable); + super.initState(); + } + + deleteBpRecord(bpId) async { + AppSettings.preLoaderDialog(context); + bool status = await AppSettings.deleteBPDetails(bpId,widget.customerId); + + if (status) { + Navigator.of(context, rootNavigator: true).pop(); + + AppSettings.longSuccessToast("BP record deleted successfully"); + await getBPHistoryDetails(dateItemsVariable); + } else { + Navigator.of(context, rootNavigator: true).pop(); + + AppSettings.longFailedToast("BP record deletion failed"); + } + } + + Widget renderzUi() { + if (FilteredList.length != 0) { + FilteredList.sort((a, b) => b.actualDate.compareTo(a.actualDate)); + return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Padding( + padding: EdgeInsets.fromLTRB(10, 10, 10, 10), + child: DropdownButtonFormField( + // Initial Value + value: dateItemsVariable, + isExpanded: true, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.calendar_month, + color: primaryColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + labelText: 'Select Date Range', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + + hint: Text('Units'), + // Down Arrow Icon + //icon: const Icon(Icons.keyboard_arrow_down), + + // Array list of items + items: dateItems.map((String items) { + return DropdownMenuItem( + value: items, + child: Text( + items, + style: TextStyle( + fontSize: 16, + ), + textAlign: TextAlign.center, + )); + }).toList(), + // After selecting the desired option,it will + // change button value to selected value + onChanged: (String? newValue) { + setState(() { + dateItemsVariable = newValue!; + }); + getBPHistoryDetails(dateItemsVariable); + }, + ), + ), + IconButton( + onPressed: () { + /* Navigator.push( + context, + MaterialPageRoute(builder: (context) => Bpchart()), + );*/ + // showBMIAdddialog(); + }, + icon: Icon( + Icons.auto_graph, + color: primaryColor, + ), + ), + Expanded( + child: ListView.builder( + padding: EdgeInsets.all(0), + itemCount: FilteredList.length, + itemBuilder: (BuildContext context, int index) { + return Slidable( + key: const ValueKey(0), + endActionPane: ActionPane( + // A motion is a widget used to control how the pane animates. + motion: ScrollMotion(), + + dragDismissible: false, + // A pane can dismiss the Slidable. + dismissible: DismissiblePane(onDismissed: () { + deleteBpRecord(FilteredList[index].bpId); + }), + + // All actions are defined in the children parameter. + children: [ + // A SlidableAction can have an icon and/or a label. + SlidableAction( + backgroundColor: Color(0xFFFE4A49), + foregroundColor: Colors.white, + icon: Icons.delete, + label: 'Delete', + onPressed: (BuildContext context) { + deleteBpRecord(FilteredList[index].bpId); + }, + ), + ], + ), + child: Card( + color: Colors.white, + child: Padding( + padding: EdgeInsets.all(8), + child: Container( + //width: MediaQuery.of(context).size.width * .55, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + /* Image( + image: const AssetImage('images/height.png'), + height: 25, + width: 25, + fit: BoxFit.fill),*/ + Text( + 'Systolic', + style: TextStyle(color: primaryColor), + ), + SizedBox( + width: 5, + ), + Padding( + padding: EdgeInsets.all(1), + child: Text( + FilteredList[index] + .systolic + .toString() + .toUpperCase(), + style: valuesTextStyle()), + ) + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Diastolic', + style: TextStyle(color: primaryColor), + ), + Padding( + padding: EdgeInsets.all(1), + child: Text( + FilteredList[index] + .diastolic + .toString() + .toUpperCase(), + style: valuesTextStyle()), + ) + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image( + image: const AssetImage( + 'images/height.png'), + height: 25, + width: 25, + fit: BoxFit.fill), + Padding( + padding: EdgeInsets.all(5), + child: Text( + FilteredList[index] + .bpText + .toString() + .toUpperCase(), + style: valuesTextStyle()), + ) + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image( + image: + const AssetImage('images/date.png'), + height: 25, + width: 25, + fit: BoxFit.fill), + Padding( + padding: EdgeInsets.all(5), + child: Text( + FilteredList[index] + .actualDate + .toString() + .toUpperCase(), + style: valuesTextStyle()), + ) + ], + ), + ], + ), + ), + ), + )); + })), + ]); + } else { + return Center( + child: Padding( + padding: EdgeInsets.fromLTRB(0, 40, 0, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + height: MediaQuery.of(context).size.height * .25, + ), + Text('No data'), + SizedBox( + height: 20, + ), + CircleAvatar( + backgroundColor: primaryColor, + radius: 40, + child: IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.white, + ), + onPressed: () async { + Navigator.push(context, MaterialPageRoute(builder: (context) => BPCalculator(customerId: widget.customerId,))).then((value) { + getBPHistoryDetails(dateItemsVariable); + }); + }, + ), + ) + ], + ), + )); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppSettings.appBar('Blood Pressure'), + body: isLoading + ? Center( + child: CircularProgressIndicator( + color: primaryColor, + strokeWidth: 5.0, + ), + ) + : renderzUi(), + floatingActionButton: Visibility( + visible:FilteredList.length!=0, + child: CircleAvatar( + backgroundColor: buttonColors, + radius: 40, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.black, + ), + onPressed: () async { + Navigator.push(context, MaterialPageRoute(builder: (context) => BPCalculator(customerId: widget.customerId,))).then((value) { + getBPHistoryDetails(dateItemsVariable); + }); + }, + ), + /* Padding( + padding: EdgeInsets.fromLTRB(5, 0, 5, 5), + child: Text( + 'Add Tanks ', + style: TextStyle(color: Colors.white), + ), + )*/ + ], + ), + ), + ), + ); + } +} diff --git a/lib/patient_dashboard/Reports/add_reports.dart b/lib/patient_dashboard/Reports/add_reports.dart new file mode 100644 index 0000000..07c7473 --- /dev/null +++ b/lib/patient_dashboard/Reports/add_reports.dart @@ -0,0 +1,1274 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:doctor/common/zoom_image.dart'; +import 'package:doctor/models/get_connected_doctors_model.dart'; +import 'package:intl/intl.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:multi_image_picker/multi_image_picker.dart'; + +class AddReports extends StatefulWidget { + String? customerId; + String? patName; + String? patAge; + String? patGender; + AddReports({this.customerId,this.patName,this.patAge,this.patGender}); + + + @override + State createState() => _AddReportsState(); +} + +class _AddReportsState extends State { + + TextEditingController doctorNameController = TextEditingController(); + TextEditingController hospitalNameController = TextEditingController(); + TextEditingController problemController = TextEditingController(); + TextEditingController dateInput = TextEditingController(); + TextEditingController patientNameController = TextEditingController(); + TextEditingController patientAgeController = TextEditingController(); + final ImagePicker _picker = ImagePicker(); + String Url = ''; + final ImagePicker imagePicker = ImagePicker(); + List imageFileList = []; + List imageFileListReports = []; + List imageFileListPrescriptions = []; + List uiFindingsImages = []; + List uiReportsImages = []; + List uiPrescriptionImages = []; + Map findings={}; + List images = []; + String _error = 'No Error Dectected'; + String apiMultiImages = ''; + String findingPictureId = ''; + String reportsPictureId = ''; + String prescriptionPictureId = ''; + Map reports={}; + Map prescriptions={}; + String? prescriptionFor; + String? problemCategory; + String? gender; + var doctorNameVariable; + List connectedDoctorsListOriginal = []; + + Future getAllConnectedDoctors() async { + try { + var response = await AppSettings.getAllConnectedDoctors(widget.customerId); + + setState(() { + connectedDoctorsListOriginal = ((jsonDecode(response)['doctors']) as List) + .map((dynamic model) { + return GetConnectedDoctorsModel.fromJson(model); + }).toList(); + //connectedDoctorsListOriginal=connectedDoctorsListOriginal.reversed.toList(); + //dateItemsVariable=connectedDoctorsListOriginal[0].doctor_name; + }); + } catch (e) { + AppSettings.longFailedToast('There is an issue please wait some time'); + } + } + + @override + void initState() { + getAllConnectedDoctors(); + super.initState(); + } + + Future pickImageFromGallery() async { + imageFileList = []; + final List? selectedImages = await imagePicker.pickMultiImage(); + AppSettings.preLoaderDialog(context); + if (selectedImages!.isNotEmpty) { + imageFileList.addAll(selectedImages); + } + + var res = await AppSettings.uploadFindingsGallery(imageFileList,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiFindingsImages = jsonDecode(res)['findingsPictureUpload']['findings']; + findings=jsonDecode(res)['findingsPictureUpload']; + findingPictureId=jsonDecode(res)['findingsPictureUpload']['findingsPictureId']; + + }); + } + + Future takeImageFromCamera() async { + try { + final image = await _picker.pickImage(source: ImageSource.camera); + if (image == null) return; + final imageTemp = File(image.path); + AppSettings.preLoaderDialog(context); + var res = await AppSettings.uploadFindingsCamera(image,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiFindingsImages = jsonDecode(res)['findingsPictureUpload']['findings']; + findings=jsonDecode(res)['findingsPictureUpload']; + findingPictureId=jsonDecode(res)['findingsPictureUpload']['findingsPictureId']; + }); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + Future pickImageFromGalleryForAddFindings() async { + imageFileList = []; + final List? selectedImages = await imagePicker.pickMultiImage(); + AppSettings.preLoaderDialog(context); + if (selectedImages!.isNotEmpty) { + imageFileList.addAll(selectedImages); + } + + var res = await AppSettings.addFindingsGallery(imageFileList,findingPictureId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiFindingsImages = jsonDecode(res)['findingsPictureUpload']['findings']; + findings=jsonDecode(res)['findingsPictureUpload']; + findingPictureId=jsonDecode(res)['findingsPictureUpload']['findingsPictureId']; + + }); + } + + Future takeImageFromCameraForAddFindings() async { + try { + final image = await _picker.pickImage(source: ImageSource.camera); + if (image == null) return; + final imageTemp = File(image.path); + AppSettings.preLoaderDialog(context); + var res = await AppSettings.addFindingsCamera(image,findingPictureId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiFindingsImages = jsonDecode(res)['findingsPictureUpload']['findings']; + findings=jsonDecode(res)['findingsPictureUpload']; + findingPictureId=jsonDecode(res)['findingsPictureUpload']['findingsPictureId']; + }); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + Future takeImageFromCameraForReports() async { + try { + final image = await _picker.pickImage(source: ImageSource.camera); + if (image == null) return; + final imageTemp = File(image.path); + AppSettings.preLoaderDialog(context); + var res = await AppSettings.uploadReportsCamera(image,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiReportsImages = jsonDecode(res)['reportsPictureUpload']['reports']; + reports=jsonDecode(res)['reportsPictureUpload']; + reportsPictureId=jsonDecode(res)['reportsPictureUpload']['reportsPictureId']; + }); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + Future pickImageFromGalleryForReports() async { + imageFileListReports = []; + final List? selectedImages = await imagePicker.pickMultiImage(); + AppSettings.preLoaderDialog(context); + if (selectedImages!.isNotEmpty) { + imageFileListReports.addAll(selectedImages); + } + + var res = await AppSettings.uploadReportsGallery(imageFileListReports,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiReportsImages = jsonDecode(res)['reportsPictureUpload']['reports']; + reports=jsonDecode(res)['reportsPictureUpload']; + reportsPictureId=jsonDecode(res)['reportsPictureUpload']['reportsPictureId']; + }); + } + + Future takeImageFromCameraForAddReports() async { + try { + final image = await _picker.pickImage(source: ImageSource.camera); + if (image == null) return; + final imageTemp = File(image.path); + AppSettings.preLoaderDialog(context); + var res = await AppSettings.addReportsCamera(image,reportsPictureId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiReportsImages = jsonDecode(res)['reportsPictureUpload']['reports']; + reports=jsonDecode(res)['reportsPictureUpload']; + reportsPictureId=jsonDecode(res)['reportsPictureUpload']['reportsPictureId']; + }); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + Future pickImageFromGalleryForAddReports() async { + imageFileListReports = []; + final List? selectedImages = await imagePicker.pickMultiImage(); + AppSettings.preLoaderDialog(context); + if (selectedImages!.isNotEmpty) { + imageFileListReports.addAll(selectedImages); + } + + var res = await AppSettings.addReportsGallery(imageFileListReports,reportsPictureId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiReportsImages = jsonDecode(res)['reportsPictureUpload']['reports']; + reports=jsonDecode(res)['reportsPictureUpload']; + reportsPictureId=jsonDecode(res)['reportsPictureUpload']['reportsPictureId']; + }); + } + + Future takeImageFromCameraForPrescriptions() async { + try { + final image = await _picker.pickImage(source: ImageSource.camera); + if (image == null) return; + final imageTemp = File(image.path); + AppSettings.preLoaderDialog(context); + var res = await AppSettings.uploadPrescriptionsCamera(image,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + + uiPrescriptionImages = jsonDecode(res)['prescriptionsPictureUpload']['precription']; + prescriptions=jsonDecode(res)['prescriptionsPictureUpload']; + prescriptionPictureId=jsonDecode(res)['prescriptionsPictureUpload']['prescriptionPictureId']; + + }); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + Future pickImageFromGalleryForPrescriptions() async { + // imageFileListPrescriptions = []; + final List? selectedImages = await imagePicker.pickMultiImage(); + AppSettings.preLoaderDialog(context); + if (selectedImages!.isNotEmpty) { + imageFileListPrescriptions.addAll(selectedImages); + } + + var res = await AppSettings.uploadPrescriptionsGallery( + imageFileListPrescriptions,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiPrescriptionImages = jsonDecode(res)['prescriptionsPictureUpload']['precription']; + prescriptions=jsonDecode(res)['prescriptionsPictureUpload']; + prescriptionPictureId=jsonDecode(res)['prescriptionsPictureUpload']['prescriptionPictureId']??''; + }); + } + + Future takeImageFromCameraForAddPrescriptions() async { + try { + final image = await _picker.pickImage(source: ImageSource.camera); + if (image == null) return; + final imageTemp = File(image.path); + AppSettings.preLoaderDialog(context); + var res = await AppSettings.addPrescriptionsCamera(image,prescriptionPictureId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiPrescriptionImages = jsonDecode(res)['prescriptionsPictureUpload']['precription']; + prescriptions=jsonDecode(res)['prescriptionsPictureUpload']; + prescriptionPictureId=jsonDecode(res)['prescriptionsPictureUpload']['prescriptionPictureId']; + }); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + Future pickImageFromGalleryForAddPrescriptions() async { + imageFileListPrescriptions = []; + final List? selectedImages = await imagePicker.pickMultiImage(); + AppSettings.preLoaderDialog(context); + if (selectedImages!.isNotEmpty) { + imageFileListPrescriptions.addAll(selectedImages); + } + + var res = await AppSettings.addPrescriptionsGallery(imageFileListPrescriptions,prescriptionPictureId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiPrescriptionImages = jsonDecode(res)['prescriptionsPictureUpload']['precription']; + prescriptions=jsonDecode(res)['prescriptionsPictureUpload']; + prescriptionPictureId=jsonDecode(res)['prescriptionsPictureUpload']['prescriptionPictureId']; + }); + } + + Future onWillPop() async { + final shouldPop = await showDialog(context: context, builder: (context) { + return AlertDialog( + title: const Text('Do you want to leave this page', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + actionsAlignment: MainAxisAlignment.spaceBetween, + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: const Text('Yes', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(false); + }, + child: const Text('No', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + ], + ); + }, + ); + return shouldPop!; + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async => onWillPop(), + child: Scaffold( + appBar: AppSettings.appBar('Add Record'), + body: SingleChildScrollView( + child: Container( + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: connectedDoctorsListOriginal.length!=0?DropdownButtonFormField( + value: doctorNameVariable, + isExpanded: true, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.person, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + labelText: 'Select Doctor', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + + hint: Text('Please Select Doctor'), + // Down Arrow Icon + //icon: const Icon(Icons.keyboard_arrow_down), + + // Array list of items + items: connectedDoctorsListOriginal.map((items) { + return DropdownMenuItem( + value: items, + child: Text( + items.doctor_name, + style: TextStyle( + fontSize: 16, + ), + textAlign: TextAlign.center, + )); + }).toList(), + // After selecting the desired option,it will + // change button value to selected value + onChanged: ( newValue) { + setState(() { + doctorNameVariable = newValue; + }); + }, + ): + IconButton( + onPressed: () { + /*Navigator.push(context, MaterialPageRoute(builder: (context) => AddDoctor())).then((value) { + getAllConnectedDoctors(); + });*/ + }, + icon: Icon( + Icons.add, + color: primaryColor, + size: 40, + ), + ),), + SizedBox( + height: MediaQuery.of(context).size.height * .02, + ), + Container( + child: TextFormField( + cursorColor: greyColor, + controller: problemController, + textCapitalization: TextCapitalization.words, + decoration: textFormFieldDecorationGrey( + Icons.report_problem, 'Enter Problem'), + ), + ), + SizedBox( + height: MediaQuery.of(context).size.height * .02, + ), + Container( + child: TextFormField( + cursorColor: greyColor, + controller: dateInput, + decoration: textFormFieldDecorationGrey( + Icons.calendar_today, 'Enter Date'), + readOnly: true, + onTap: () async { + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1950), + lastDate: DateTime.now(), + builder: (BuildContext context, Widget? child) { + return Theme( + data: ThemeData.dark().copyWith( + colorScheme: ColorScheme.dark( + primary: buttonColors, + onPrimary: Colors.white, + surface: buttonColors, + onSurface: Colors.white, + ), + dialogBackgroundColor: primaryColor, + ), + child: child!, + ); + }, + ); + + if (pickedDate != null) { + print( + pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000 + String formattedDate = + DateFormat('dd-MM-yyyy').format(pickedDate); + print( + formattedDate); //formatted date output using intl package => 2021-03-16 + setState(() { + dateInput.text = + formattedDate; //set output date to TextField value. + }); + } else {} + }, + ), + ), + SizedBox( + height: MediaQuery.of(context).size.height * .02, + ), + Text('Select Problem Category', + style: TextStyle(color: Colors.red,fontWeight: FontWeight.bold,fontSize: 14),), + Row( + children: [ + Expanded( + child: RadioListTile( + title: Text("General"), + value: "general", + groupValue: problemCategory, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + problemCategory = value.toString(); + }); + }, + ), + ), + Expanded( + child: RadioListTile( + title: Text("Confidential"), + value: "confidential", + groupValue: problemCategory, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + problemCategory = value.toString(); + }); + }, + ), + ), + ], + ), + Text('Select Problem For', + style: TextStyle(color: Colors.red,fontWeight: FontWeight.bold,fontSize: 14),), + Row( + children: [ + Expanded( + child: RadioListTile( + title: Text("For Yourself"), + value: "self", + groupValue: prescriptionFor, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + prescriptionFor = value.toString(); + }); + }, + ), + ), + Expanded( + child: RadioListTile( + title: Text("For Family"), + value: "others", + groupValue: prescriptionFor, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + prescriptionFor = value.toString(); + }); + }, + ), + ), + ], + ), + Visibility( + visible: + prescriptionFor.toString().toLowerCase() == 'others', + child: Container( + child: TextFormField( + cursorColor: greyColor, + controller: patientNameController, + decoration: textFormFieldDecoration( + Icons.person, 'Enter patient name'), + ), + ), + ), + SizedBox( + height: MediaQuery.of(context).size.height * .02, + ), + Visibility( + visible: + prescriptionFor.toString().toLowerCase() == 'others', + child: Container( + child: TextFormField( + cursorColor: greyColor, + keyboardType: TextInputType.number, + controller: patientAgeController, + decoration: textFormFieldDecoration( + Icons.person, 'Enter patient age'), + ), + ), + ), + Visibility( + visible: + prescriptionFor.toString().toLowerCase() == 'others', + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: RadioListTile( + title: Text("Male", style: TextStyle(fontSize: 10)), + value: "male", + groupValue: gender, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + gender = value.toString(); + }); + }, + ), + ), + Expanded( + child: RadioListTile( + title: Text( + "Female", + style: TextStyle(fontSize: 10), + ), + value: "female", + groupValue: gender, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + gender = value.toString(); + }); + }, + ), + ), + Expanded( + child: RadioListTile( + title: + Text("Others", style: TextStyle(fontSize: 10)), + value: "other", + groupValue: gender, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + gender = value.toString(); + }); + }, + ), + ), + ], + ), + ), + + /*findings*/ + Visibility( + visible: uiFindingsImages.length == 0, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCamera(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGallery(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + child: const Text('Select Findings'), + ), + ), + Visibility( + visible: uiFindingsImages.length > 0, + child: Container( + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: uiFindingsImages.length, + itemBuilder: (context, index) { + return Column( + children: [ + Card( + child: GestureDetector( + onTap: () { + + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Findings',imageDetails:uiFindingsImages[index]['url']))); + /*gridOntap(index);*/ + }, + child: Container( + width: MediaQuery.of(context).size.width * + .30, + height: + MediaQuery.of(context).size.height * + .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + uiFindingsImages[index]['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + child: Stack(children: [ + Positioned( + right: 0, + child: Container( + child: IconButton( + iconSize: 30, + icon: const Icon( + Icons.cancel, + color: Colors.red, + ), + onPressed: () async { + AppSettings.preLoaderDialog(context); + + String fileName = uiFindingsImages[index]['url'].split('/').last; + try{ + var response = await AppSettings.deleteFindings(fileName,findingPictureId,widget.customerId); + print(jsonDecode(response)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiFindingsImages = jsonDecode(response)['findingsPictureUpload']['findings']; + }); + } + catch(e){ + Navigator.of(context, rootNavigator: true).pop(); + AppSettings.longFailedToast('Image deletion failed'); + } + + }, + ), + ), + ) + ]), + ), + ), + ), + /*Expanded(child:IconButton( + icon: const Icon(Icons.remove,color: Colors.red,), + + onPressed: () async{ + + }, + ),)*/ + ], + ); + }), + )), + Visibility( + visible: uiFindingsImages.length != 0, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: buttonColors, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForAddFindings(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForAddFindings(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + child: const Text('Add Findings'), + ), + ), + + /*reports*/ + Visibility( + visible: uiReportsImages.length == 0, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForReports(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForReports(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + child: const Text('Select Reports'), + ), + ), + Visibility( + visible: uiReportsImages.length > 0, + child: Container( + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: uiReportsImages.length, + itemBuilder: (context, index) { + return Column( + children: [ + Card( + child: GestureDetector( + onTap: () { + + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Reports',imageDetails:uiReportsImages[index]['url']))); + /*gridOntap(index);*/ + }, + child: Container( + width: MediaQuery.of(context).size.width * + .30, + height: + MediaQuery.of(context).size.height * + .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + uiReportsImages[index]['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + child: Stack(children: [ + Positioned( + right: 0, + child: Container( + child: IconButton( + iconSize: 30, + icon: const Icon( + Icons.cancel, + color: Colors.red, + ), + onPressed: () async { + AppSettings.preLoaderDialog(context); + + String fileName = uiReportsImages[index]['url'].split('/').last; + var response = await AppSettings.deleteReports(fileName,reportsPictureId,widget.customerId); + print(jsonDecode(response)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiReportsImages = jsonDecode(response)['reportsPictureUpload']['reports']; + }); + + }, + ), + ), + ) + ]), + ), + ) + ), + /*Expanded(child:IconButton( + icon: const Icon(Icons.remove,color: Colors.red,), + + onPressed: () async{ + + }, + ),)*/ + ], + ); + }), + )), + Visibility( + visible: uiReportsImages.length != 0, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: buttonColors, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForAddReports(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForAddReports(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + child: const Text('Add Reports'), + ), + ), + + /*prescriptions*/ + Visibility( + visible: uiPrescriptionImages.length == 0, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForPrescriptions(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForPrescriptions(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + child: const Text('Select Prescriptions'), + ), + ), + Visibility( + visible: uiPrescriptionImages.length > 0, + child: Container( + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: uiPrescriptionImages.length, + itemBuilder: (context, index) { + return Column( + children: [ + Card( + child: GestureDetector( + onTap: () { + + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Prescriptions',imageDetails:uiPrescriptionImages[index]['url']))); + /*gridOntap(index);*/ + }, + child: Container( + width: MediaQuery.of(context).size.width * + .30, + height: + MediaQuery.of(context).size.height * + .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + uiPrescriptionImages[index]['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + child: Stack(children: [ + Positioned( + right: 0, + child: Container( + child: IconButton( + iconSize: 30, + icon: const Icon( + Icons.cancel, + color: Colors.red, + ), + onPressed: () async { + AppSettings.preLoaderDialog(context); + + String fileName = uiPrescriptionImages[index]['url'].split('/').last; + var response = await AppSettings.deletePrescriptions(fileName,prescriptionPictureId,widget.customerId); + print(jsonDecode(response)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiPrescriptionImages = jsonDecode(response)['prescriptionsPictureUpload']['precription']; + }); + + }, + ), + ), + ) + ]), + ), + ) + ), + /*Expanded(child:IconButton( + icon: const Icon(Icons.remove,color: Colors.red,), + + onPressed: () async{ + + }, + ),)*/ + ], + ); + }), + )), + Visibility( + visible: uiPrescriptionImages.length != 0, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: buttonColors, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForAddPrescriptions(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForAddPrescriptions(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + child: const Text('Add Prescriptions'), + ), + ), + + Container( + width: double.infinity, + height: MediaQuery.of(context).size.height * .06, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: buttonColors, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () async { + if (doctorNameVariable!=''&&problemController.text != '' && + dateInput.text != '' && + prescriptionFor != ''&&problemCategory!='') { + String _name = ''; + String _age = ''; + String? _gender = ''; + + if (prescriptionFor.toString().toLowerCase() == + 'others') { + if (patientNameController != '' && + patientAgeController.text != '' && + gender != '') { + _name = patientNameController.text; + _age = patientAgeController.text; + _gender = gender; + } else { + AppSettings.longFailedToast( + 'Please enter details'); + } + } else { + _name = widget.patName!; + _age = widget.patAge!; + _gender = widget.patGender!; + } + AppSettings.preLoaderDialog(context); + bool isOnline = + await AppSettings.internetConnectivity(); + if (isOnline) { + var payload = new Map(); + payload["problem"] = + problemController.text.toString(); + payload["doctorName"] = doctorNameVariable.doctor_name.toString(); + payload["hospitalName"] = doctorNameVariable.hospital_name.toString(); + payload["doctorId"] = doctorNameVariable.doctor_id.toString(); + payload["date"] = dateInput.text.toString(); + payload["findings_date"] = ''; + payload["reports_date"] = ''; + payload["prescription_date"] = ''; + payload["patientType"] = prescriptionFor.toString(); + payload["problemCategory"] = problemCategory.toString(); + payload["others"] = { + "name": _name, + "age": int.parse(_age), + "gender": _gender.toString().toLowerCase() + }; + payload["findings"] = uiFindingsImages; + payload["reports"] = uiReportsImages; + payload["prescription"] = uiPrescriptionImages; + + bool uploadStatus = await AppSettings.addRecords(payload,widget.customerId); + + try { + if (uploadStatus) { + Navigator.of(context, rootNavigator: true) + .pop(); + AppSettings.longSuccessToast( + 'Record added successfully'); + Navigator.pop(context); + } else { + Navigator.of(context, rootNavigator: true) + .pop(); + AppSettings.longFailedToast( + 'Fail to add record details'); + } + } catch (e) { + print(e); + Navigator.of(context, rootNavigator: true) + .pop(); + AppSettings.longFailedToast( + 'Fail to add record details'); + } + } else { + AppSettings.longFailedToast( + 'Please check internet'); + } + } else { + AppSettings.longFailedToast( + 'Please enter valid details'); + } + }, + child: const Text('Submit'), + )), + ], + ), + ), + ), + )) + ); + } + +} diff --git a/lib/patient_dashboard/Reports/all-records_onclick_new.dart b/lib/patient_dashboard/Reports/all-records_onclick_new.dart new file mode 100644 index 0000000..d43a3e7 --- /dev/null +++ b/lib/patient_dashboard/Reports/all-records_onclick_new.dart @@ -0,0 +1,1813 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:flutter/services.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:doctor/common/zoom_image.dart'; + +class AllRecordsOnClick extends StatefulWidget { + var recordDetails; + var initialIndex; + var customerId; + + AllRecordsOnClick({this.recordDetails,this.initialIndex,this.customerId}); + + @override + State createState() => _AllRecordsOnClickState(); +} + +class _AllRecordsOnClickState extends State + with TickerProviderStateMixin { + //late TabController _controller; + /*final List topTabs = [ + Tab( + child: Text( + 'Findings', + style: TextStyle(fontSize: 12), + )), + Tab( + child: Text( + 'Reports', + style: TextStyle(fontSize: 12), + )), + Tab( + child: Text( + 'Prescriptions', + style: TextStyle(fontSize: 12), + )), + ];*/ + final ImagePicker imagePicker = ImagePicker(); + List imageFileList = []; + final ImagePicker _picker = ImagePicker(); + + @override + void initState() { + //_controller = TabController(vsync: this, initialIndex: widget.initialIndex, length: topTabs.length); + super.initState(); + } + + Future pickImageFromGalleryForUpdateFindings() async { + imageFileList = []; + final List? selectedImages = await imagePicker.pickMultiImage(); + AppSettings.preLoaderDialog(context); + if (selectedImages!.isNotEmpty) { + imageFileList.addAll(selectedImages); + } + + var res = await AppSettings.updateFindingsGallery( + imageFileList, widget.recordDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + widget.recordDetails.findingsImages = jsonDecode(res)['findings']; + }); + } + + Future takeImageFromCameraForUpdateFindings() async { + try { + final image = await _picker.pickImage(source: ImageSource.camera); + if (image == null) return; + final imageTemp = File(image.path); + AppSettings.preLoaderDialog(context); + var res = await AppSettings.updateFindingsCamera( + image, widget.recordDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + widget.recordDetails.findingsImages = jsonDecode(res)['findings']; + }); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + Future pickImageFromGalleryForUpdateReports() async { + imageFileList = []; + final List? selectedImages = await imagePicker.pickMultiImage(); + AppSettings.preLoaderDialog(context); + if (selectedImages!.isNotEmpty) { + imageFileList.addAll(selectedImages); + } + + var res = await AppSettings.updateReportsGallery( + imageFileList, widget.recordDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + widget.recordDetails.reportImages = jsonDecode(res)['reports']; + }); + } + + Future takeImageFromCameraForUpdateReports() async { + try { + final image = await _picker.pickImage(source: ImageSource.camera); + if (image == null) return; + final imageTemp = File(image.path); + AppSettings.preLoaderDialog(context); + var res = await AppSettings.updateReportsCamera( + image, widget.recordDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + widget.recordDetails.reportImages = jsonDecode(res)['reports']; + }); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + Future pickImageFromGalleryForUpdatePrescriptions() async { + imageFileList = []; + final List? selectedImages = await imagePicker.pickMultiImage(); + AppSettings.preLoaderDialog(context); + if (selectedImages!.isNotEmpty) { + imageFileList.addAll(selectedImages); + } + + var res = await AppSettings.updatePrescriptionsGallery( + imageFileList, widget.recordDetails.recordId,widget); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + widget.recordDetails.prescriptionImages = jsonDecode(res)['prescription']; + }); + } + + Future takeImageFromCameraForUpdatePrescriptions() async { + try { + final image = await _picker.pickImage(source: ImageSource.camera); + if (image == null) return; + final imageTemp = File(image.path); + AppSettings.preLoaderDialog(context); + var res = await AppSettings.updatePrescriptionsCamera( + image, widget.recordDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + widget.recordDetails.prescriptionImages = + jsonDecode(res)['prescription']; + }); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + + Widget renderUiForFindings() { + if (widget.recordDetails.findingsImages.length != 0) { + return Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: GridView.builder( + itemCount: widget.recordDetails.findingsImages.length, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, + crossAxisSpacing: 2.0, + mainAxisSpacing: 2.0, + ), + itemBuilder: (BuildContext context, int index) { + return GestureDetector( + onTap: () { + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage( + imageName: 'Findings', + imageDetails: widget.recordDetails + .findingsImages[index]['url']))); + /*gridOntap(index);*/ + }, + child: Container( + width: MediaQuery.of(context).size.width * .30, + height: MediaQuery.of(context).size.height * .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + widget.recordDetails.findingsImages[index] + ['url']) as ImageProvider, // picked file + fit: BoxFit.fill)), + child: Stack(children: [ + Positioned( + right: 0, + child: Container( + child: IconButton( + iconSize: 30, + icon: const Icon( + Icons.delete, + color: Colors.red, + ), + onPressed: () async { + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) => AlertDialog( + title: + const Text('Do you want to delete image?', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + actionsAlignment: + MainAxisAlignment.spaceBetween, + actions: [ + TextButton( + onPressed: () async { + AppSettings.preLoaderDialog(context); + + String fileName = widget.recordDetails + .findingsImages[index]['url'] + .split('/') + .last; + + var payload = new Map(); + payload["urlType"] = 'findings'; + payload["url"] = widget.recordDetails + .findingsImages[index]['url']; + + // bool deleteStatus = await AppSettings.deleteRecordsNew(payload,widget.recordId); + try { + var res = + await AppSettings.deleteRecordsNew( + payload, + widget.recordDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longSuccessToast( + "Image deleted Successfully"); + setState(() { + widget.recordDetails.findingsImages = + jsonDecode(res)['remainingUrls']; + }); + } catch (e) { + print(e); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longFailedToast( + "Image deletion failed"); + } + }, + child: const Text('Yes', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: const Text('No', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + ], + ), + ); + }, + ), + /* color: Colors.pinkAccent, + width: 35, + height: 35,*/ + ), + ) + ]), + ), + + //Image.network(widget.imageDetails[index]['url']), + ); + }, + )), + Padding( + padding: EdgeInsets.fromLTRB(8, 8, 8, 8), + child: CircleAvatar( + backgroundColor: primaryColor, + radius: 40, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.white, + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdateFindings(); + Navigator.pop(context); + }, + ), + SizedBox( + width: MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdateFindings(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + ), + ], + ), + ), + ), + ], + ); + } else { + return Center( + child: Padding( + padding: EdgeInsets.fromLTRB(0, 40, 0, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + height: MediaQuery.of(context).size.height * .25, + ), + Text('Click below icon to add new findings'), + SizedBox( + height: 20, + ), + CircleAvatar( + backgroundColor: primaryColor, + radius: 40, + child: IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.white, + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdateFindings(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdateFindings(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + ), + ) + ], + ), + )); + } + } + + Widget renderUiForReports() { + if (widget.recordDetails.reportImages.length != 0) { + return Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: GridView.builder( + itemCount: widget.recordDetails.reportImages.length, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, + crossAxisSpacing: 2.0, + mainAxisSpacing: 2.0, + ), + itemBuilder: (BuildContext context, int index) { + return GestureDetector( + onTap: () { + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage( + imageName: 'Findings', + imageDetails: widget + .recordDetails.reportImages[index]['url']))); + /*gridOntap(index);*/ + }, + child: Container( + width: MediaQuery.of(context).size.width * .30, + height: MediaQuery.of(context).size.height * .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + widget.recordDetails.reportImages[index] + ['url']) as ImageProvider, // picked file + fit: BoxFit.fill)), + child: Stack(children: [ + Positioned( + right: 0, + child: Container( + child: IconButton( + iconSize: 30, + icon: const Icon( + Icons.delete, + color: Colors.red, + ), + onPressed: () async { + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) => AlertDialog( + title: + const Text('Do you want to delete image?', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + actionsAlignment: + MainAxisAlignment.spaceBetween, + actions: [ + TextButton( + onPressed: () async { + AppSettings.preLoaderDialog(context); + + String fileName = widget.recordDetails + .reportImages[index]['url'] + .split('/') + .last; + + var payload = new Map(); + payload["urlType"] = 'reports'; + payload["url"] = widget.recordDetails + .reportImages[index]['url']; + + try { + var res = + await AppSettings.deleteRecordsNew( + payload, + widget.recordDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longSuccessToast( + "Image deleted Successfully"); + setState(() { + widget.recordDetails.reportImages = + jsonDecode(res)['remainingUrls']; + }); + } catch (e) { + print(e); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longFailedToast( + "Image deletion failed"); + } + }, + child: const Text('Yes', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: const Text('No', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + ], + ), + ); + }, + ), + /* color: Colors.pinkAccent, + width: 35, + height: 35,*/ + ), + ) + ]), + ), + + //Image.network(widget.imageDetails[index]['url']), + ); + }, + )), + Padding( + padding: EdgeInsets.fromLTRB(8, 8, 8, 8), + child: CircleAvatar( + backgroundColor: primaryColor, + radius: 40, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.white, + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdateReports(); + Navigator.pop(context); + }, + ), + SizedBox( + width: MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdateReports(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + ), + ], + ), + ), + ), + ], + ); + } else { + return Center( + child: Padding( + padding: EdgeInsets.fromLTRB(0, 40, 0, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + height: MediaQuery.of(context).size.height * .25, + ), + Text('Click below icon to add new Report'), + SizedBox( + height: 20, + ), + CircleAvatar( + backgroundColor: primaryColor, + radius: 40, + child: IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.white, + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdateReports(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdateReports(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + ), + ) + ], + ), + )); + } + } + + Widget renderUiForPrescriptions() { + if (widget.recordDetails.prescriptionImages.length != 0) { + return Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: GridView.builder( + itemCount: widget.recordDetails.prescriptionImages.length, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, + crossAxisSpacing: 2.0, + mainAxisSpacing: 2.0, + ), + itemBuilder: (BuildContext context, int index) { + return GestureDetector( + onTap: () { + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage( + imageName: 'Prescripitons', + imageDetails: widget.recordDetails + .prescriptionImages[index]['url']))); + /*gridOntap(index);*/ + }, + child: Container( + width: MediaQuery.of(context).size.width * .30, + height: MediaQuery.of(context).size.height * .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + widget.recordDetails.prescriptionImages[index] + ['url']) as ImageProvider, // picked file + fit: BoxFit.fill)), + child: Stack(children: [ + Positioned( + right: 0, + child: Container( + child: IconButton( + iconSize: 30, + icon: const Icon( + Icons.delete, + color: Colors.red, + ), + onPressed: () async { + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) => AlertDialog( + title: + const Text('Do you want to delete image?', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + actionsAlignment: + MainAxisAlignment.spaceBetween, + actions: [ + TextButton( + onPressed: () async { + AppSettings.preLoaderDialog(context); + + String fileName = widget.recordDetails + .prescriptionImages[index]['url'] + .split('/') + .last; + + var payload = + new Map(); + payload["urlType"] = 'prescription'; + payload["url"] = widget.recordDetails + .prescriptionImages[index]['url']; + + try { + var res = await AppSettings + .deleteRecordsNew( + payload, + widget + .recordDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longSuccessToast( + "Image deleted Successfully"); + setState(() { + widget.recordDetails + .prescriptionImages = + jsonDecode( + res)['remainingUrls']; + }); + } catch (e) { + print(e); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longFailedToast( + "Image deletion failed"); + } + }, + child: const Text('Yes', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: const Text('No', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + ], + ), + ); + }, + ), + ), + ) + ]), + ), + + //Image.network(widget.imageDetails[index]['url']), + ); + }, + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsets.fromLTRB(8, 8, 8, 8), + child: CircleAvatar( + backgroundColor: primaryColor, + radius: 40, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + iconSize: 40, + icon: const Icon( + Icons.shopping_cart, + color: Colors.white, + ), + onPressed: () { + /*Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new OrderMedicines( + prescriptionDetails: widget.recordDetails)));*/ + //signup screen + }, + ), + ], + ), + ), + ), + Padding( + padding: EdgeInsets.fromLTRB(8, 8, 8, 8), + child: CircleAvatar( + backgroundColor: primaryColor, + radius: 40, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.white, + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdatePrescriptions(); + Navigator.pop(context); + }, + ), + SizedBox( + width: MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdatePrescriptions(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + ), + ], + ), + ), + ), + ], + ) + ], + ); + } else { + return Center( + child: Padding( + padding: EdgeInsets.fromLTRB(0, 40, 0, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + height: MediaQuery.of(context).size.height * .25, + ), + Text('Click below icon to add new Prescriptions'), + SizedBox( + height: 20, + ), + CircleAvatar( + backgroundColor: primaryColor, + radius: 40, + child: IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.white, + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdatePrescriptions(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdatePrescriptions(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + ), + ) + ], + ), + )); + } + } + + Widget prescriptions(var obj){ + if(obj.prescriptionImages.length!=0){ + return Container( + //color: secondaryColor, + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: Row( + children: [ + Expanded(child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: obj.prescriptionImages.length, + itemBuilder: (context, index) { + return Row( + children: [ + Card( + child: GestureDetector( + onTap: (){ + //showPicDialog(obj.prescriptionImages[index]['url']); + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Prescriptions',imageDetails:obj.prescriptionImages[index]['url'])));}, + child: Container( + width: MediaQuery.of(context).size.width * .30, + height: MediaQuery.of(context).size.height * .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + obj.prescriptionImages[index]['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + child: Stack(children: [ + Positioned( + right: 0, + child: Container( + child: IconButton( + iconSize: 30, + icon: const Icon( + Icons.delete, + color: Colors.red, + ), + onPressed: () async { + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) => AlertDialog( + title: + const Text('Do you want to delete image?', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + actionsAlignment: + MainAxisAlignment.spaceBetween, + actions: [ + TextButton( + onPressed: () async { + AppSettings.preLoaderDialog(context); + + String fileName = obj.prescriptionImages[index]['url'] + .split('/') + .last; + + var payload = + new Map(); + payload["urlType"] = 'prescription'; + payload["url"] = obj.prescriptionImages[index]['url']; + + try { + var res = await AppSettings.deleteRecordsNew(payload, obj.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + Navigator.of(context).pop(true); + AppSettings.longSuccessToast("Image deleted Successfully"); + setState(() { + obj.prescriptionImages = + jsonDecode( + res)['remainingUrls']; + }); + } catch (e) { + print(e); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longFailedToast( + "Image deletion failed"); + } + }, + child: const Text('Yes', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: const Text('No', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + ], + ), + ); + }, + ), + ), + ) + ]), + ), + ), + ) + + ], + ); + }),), + Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.green, + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdatePrescriptions(); + Navigator.pop(context); + }, + ), + SizedBox( + width: MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdatePrescriptions(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + + + + }, + ), + IconButton( + iconSize: 40, + icon: const Icon( + Icons.shopping_cart, + color: primaryColor, + ), + onPressed: () { + /*Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new OrderMedicines( + prescriptionDetails: widget.recordDetails)));*/ + //signup screen + }, + ), + ], + ) + + ], + ) + ); + } + else{ + return GestureDetector( + onTap: (){ + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdatePrescriptions(); + Navigator.pop(context); + }, + ), + SizedBox( + width: MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdatePrescriptions(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + child: Row( + children: [ + Icon( + Icons.add, + color: Colors.green, + size: 40, + ), + Text('Add Prescriptions',style: textButtonStyle(),) + ], + ), + ); + } + + + + } + + Widget findings(var obj){ + if(obj.findingsImages.length!=0){ + return Container( + //color: secondaryColor, + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: Row( + children: [ + Expanded(child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: obj.findingsImages.length, + itemBuilder: (context, index) { + return Row( + children: [ + Card( + child: GestureDetector( + onTap: (){ + //showPicDialog(obj.prescriptionImages[index]['url']); + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Findings',imageDetails:obj.findingsImages[index]['url'])));}, + child: Container( + width: MediaQuery.of(context).size.width * .30, + height: MediaQuery.of(context).size.height * .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + obj.findingsImages[index]['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + child: Stack(children: [ + Positioned( + right: 0, + child: Container( + child: IconButton( + iconSize: 30, + icon: const Icon( + Icons.delete, + color: Colors.red, + ), + onPressed: () async { + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) => AlertDialog( + title: + const Text('Do you want to delete image?', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + actionsAlignment: + MainAxisAlignment.spaceBetween, + actions: [ + TextButton( + onPressed: () async { + AppSettings.preLoaderDialog(context); + + String fileName = widget.recordDetails + .findingsImages[index]['url'] + .split('/') + .last; + + var payload = new Map(); + payload["urlType"] = 'findings'; + payload["url"] = widget.recordDetails + .findingsImages[index]['url']; + + // bool deleteStatus = await AppSettings.deleteRecordsNew(payload,widget.recordId); + try { + var res = + await AppSettings.deleteRecordsNew( + payload, + widget.recordDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longSuccessToast( + "Image deleted Successfully"); + setState(() { + widget.recordDetails.findingsImages = + jsonDecode(res)['remainingUrls']; + }); + } catch (e) { + print(e); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longFailedToast( + "Image deletion failed"); + } + }, + child: const Text('Yes', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: const Text('No', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + ], + ), + ); + }, + ), + /* color: Colors.pinkAccent, + width: 35, + height: 35,*/ + ), + ) + ]), + ), + ), + ) + + ], + ); + }),), + IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.green, + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdateFindings(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdateFindings(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + ) + + ], + ) + ); + } + else{ + return GestureDetector( + onTap: (){ + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdateFindings(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdateFindings(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + + }, + child: Row( + children: [ + Icon( + Icons.add, + color: Colors.green, + size: 40, + ), + Text('Add Findings',style: textButtonStyle(),) + ], + ), + ); + } + + + + } + + Widget reports(var obj){ + if(obj.reportImages.length!=0){ + return Container( + //color: secondaryColor, + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: Row( + children: [ + Expanded(child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: obj.reportImages.length, + itemBuilder: (context, index) { + return Row( + children: [ + Card( + child: GestureDetector( + onTap: (){ + //showPicDialog(obj.prescriptionImages[index]['url']); + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Findings',imageDetails:obj.reportImages[index]['url'])));}, + child: Container( + width: MediaQuery.of(context).size.width * .30, + height: MediaQuery.of(context).size.height * .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + obj.reportImages[index]['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + child: Stack(children: [ + Positioned( + right: 0, + child: Container( + child: IconButton( + iconSize: 30, + icon: const Icon( + Icons.delete, + color: Colors.red, + ), + onPressed: () async { + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) => AlertDialog( + title: + const Text('Do you want to delete image?', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + actionsAlignment: + MainAxisAlignment.spaceBetween, + actions: [ + TextButton( + onPressed: () async { + AppSettings.preLoaderDialog(context); + + String fileName = widget.recordDetails + .reportImages[index]['url'] + .split('/') + .last; + + var payload = new Map(); + payload["urlType"] = 'reports'; + payload["url"] = widget.recordDetails + .reportImages[index]['url']; + + try { + var res = + await AppSettings.deleteRecordsNew( + payload, + widget.recordDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longSuccessToast( + "Image deleted Successfully"); + setState(() { + widget.recordDetails.reportImages = + jsonDecode(res)['remainingUrls']; + }); + } catch (e) { + print(e); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longFailedToast( + "Image deletion failed"); + } + }, + child: const Text('Yes', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: const Text('No', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + ], + ), + ); + }, + ), + /* color: Colors.pinkAccent, + width: 35, + height: 35,*/ + ), + ) + ]), + ), + ), + ) + + ], + ); + }),), + IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.green, + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdateReports(); + Navigator.pop(context); + }, + ), + SizedBox( + width: MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdateReports(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + ) + + ], + ) + ); + } + else{ + return GestureDetector( + onTap: (){ + + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdateReports(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdateReports(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + child: Row( + children: [ + Icon( + Icons.add, + color: Colors.green, + size: 40, + ), + Text('Add Reports',style: textButtonStyle(),) + ], + ), + ); + } + + + + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppSettings.appBar('Records'), + body: Padding( + padding: EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: MediaQuery.of(context).size.height * .15, + width: double.infinity, + child: Padding( + padding: EdgeInsets.all(0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Problem: ' + + widget.recordDetails.problem.toString().toUpperCase(), + style: problemTextStyle()), + Text(widget.recordDetails.doctorName.toString().toUpperCase(), + style: valuesTextStyle()), + Text( + widget.recordDetails.hospitalName + .toString() + .toUpperCase(), + style: valuesTextStyle()), + Text(widget.recordDetails.date.toString().toUpperCase(), + style: valuesTextStyle()), + Text('Patient details: ', style: problemTextStyle()), + Text( + widget.recordDetails.patient_name + .toString() + .toUpperCase(), + style: valuesTextStyle()), + Row( + children: [ + Text(widget.recordDetails.gender.toString().toUpperCase(), + style: valuesTextStyle()), + SizedBox( + width: MediaQuery.of(context).size.width * .05, + ), + Text( + widget.recordDetails.age.toString().toUpperCase() + + " Yrs", + style: valuesTextStyle()), + ], + ), + ], + ), + ), + ), + Text('Findings',style: TextStyle(color: Colors.red,fontSize: 16,fontWeight: FontWeight.bold),), + findings(widget.recordDetails), + Text('Reports',style: TextStyle(color: Colors.red,fontSize: 16,fontWeight: FontWeight.bold),), + reports(widget.recordDetails), + Text('Prescriptions',style: TextStyle(color: Colors.red,fontSize: 16,fontWeight: FontWeight.bold),), + prescriptions(widget.recordDetails) + ], + ), + ), + ); + } +} diff --git a/lib/patient_dashboard/Reports/allreports.dart b/lib/patient_dashboard/Reports/allreports.dart new file mode 100644 index 0000000..38df6f8 --- /dev/null +++ b/lib/patient_dashboard/Reports/allreports.dart @@ -0,0 +1,1294 @@ +import 'dart:convert'; + +import 'package:carousel_slider/carousel_slider.dart'; +import 'package:flutter/material.dart'; +import 'package:doctor/patient_dashboard/Reports/add_reports.dart'; +import 'package:doctor/patient_dashboard/Reports/update_report.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:doctor/common/zoom_image.dart'; +import 'package:doctor/models/reports_model.dart'; +import 'package:doctor/patient_dashboard/Reports/all-records_onclick_new.dart'; +import 'package:intl/intl.dart'; + +class AllReports extends StatefulWidget { + String? customerId; + String? patName; + String? patAge; + String? patGender; + AllReports({this.customerId,this.patName,this.patAge,this.patGender}); + + @override + State createState() => _AllReportsState(); +} + +class _AllReportsState extends State { + + + List reportsList = []; + List reportsListOriginal = []; + bool isReportsDataLoading = false; + bool isSereverIssue = false; + TextEditingController searchController = TextEditingController(); + TextEditingController dateInput = TextEditingController(); + TextEditingController fromdateController = TextEditingController(); + TextEditingController todateController = TextEditingController(); + DateTime fromDate=DateTime.now(); + String dropdownSearchType = 'Problem'; + String? searchBy; + var typeOfSearchItems = [ + 'Problem', + 'Doctor', + 'Date', + ]; + final List imgList = [ + 'images/mobilebg.png', + 'images/mobilebg2.png', + 'images/mobilebg3.png' + ]; + List images = ['img1', 'img2', 'img3']; + + Future getAllRecords() async { + isReportsDataLoading=true; + try { + var response = await AppSettings.getAllRecords(widget.customerId); + + setState(() { + reportsListOriginal = ((jsonDecode(response)) as List) + .map((dynamic model) { + return ReportsModel.fromJson(model); + }).toList(); + reportsList=reportsListOriginal.reversed.toList(); + isReportsDataLoading = false; + }); + } catch (e) { + setState(() { + isReportsDataLoading = false; + isSereverIssue = true; + }); + } + } + + Future getRecordsByProblemName(var problem) async { + + isReportsDataLoading=true; + try { + var response = await AppSettings.getAllRecords(widget.customerId); + + setState(() { + reportsListOriginal = ((jsonDecode(response)) as List) + .map((dynamic model) { + return ReportsModel.fromJson(model); + }).toList(); + reportsList=reportsListOriginal.reversed.toList(); + reportsList= reportsListOriginal.where( + (x) => x.problem.toString().toLowerCase().contains(problem.toString().toLowerCase()) + ).toList(); + isReportsDataLoading = false; + }); + } catch (e) { + setState(() { + isReportsDataLoading = false; + isSereverIssue = true; + }); + } + } + + Future getRecordsByDoctorName(var doctor) async { + + isReportsDataLoading=true; + try { + var response = await AppSettings.getAllRecords(widget.customerId); + + setState(() { + reportsListOriginal = ((jsonDecode(response)) as List) + .map((dynamic model) { + return ReportsModel.fromJson(model); + }).toList(); + reportsList=reportsListOriginal.reversed.toList(); + reportsList= reportsListOriginal.where( + (x) => x.doctorName.toString().toLowerCase().contains(doctor.toString().toLowerCase()) + ).toList(); + isReportsDataLoading = false; + }); + } catch (e) { + setState(() { + isReportsDataLoading = false; + isSereverIssue = true; + }); + } + } + + Future getRecordsByDate(var date) async { + + isReportsDataLoading=true; + try { + var response = await AppSettings.getAllRecords(widget.customerId); + + setState(() { + reportsListOriginal = ((jsonDecode(response)) as List) + .map((dynamic model) { + return ReportsModel.fromJson(model); + }).toList(); + reportsList=reportsListOriginal.reversed.toList(); + reportsList= reportsListOriginal.where( + (x) => x.date.toString().toLowerCase().contains(date.toString().toLowerCase()) + ).toList(); + isReportsDataLoading = false; + }); + } catch (e) { + setState(() { + isReportsDataLoading = false; + isSereverIssue = true; + }); + } + } + + Future getRecordsByDateRange(var fromDate,var toDate) async { + isReportsDataLoading = true; + + try { + var response = await AppSettings.getAllRecords(widget.customerId); + + setState(() { + reportsListOriginal = ((jsonDecode(response)) as List) + .map((dynamic model) { + return ReportsModel.fromJson(model); + }).toList(); + reportsList=reportsListOriginal.reversed.toList(); + var dateToCheck = DateTime.now().add(Duration(days: -1)); + + reportsList = reportsListOriginal.reversed.where((product) { + final date = product.dateForFilter; + final startDate =DateFormat('dd-MM-yyyy').parse(fromDate); + final endDate = DateFormat('dd-MM-yyyy').parse(toDate); + return date.isAfter(startDate) && date.isBefore(endDate); + + //reportsList=reportsListOriginal.reversed.toList(); + }).toList(); + + /*if( dateToCheck.isAfter(startDate) && dateToCheck.isBefore(endDate)) + { + print("dateToCheck is between now and lastYear"); + } + else + { + print("dateToCheck is not between now and lastYear"); + }*/ + + + isReportsDataLoading = false; + }); + } catch (e) { + setState(() { + isReportsDataLoading = false; + isSereverIssue = true; + }); + } + } + + @override + void initState() { + getAllRecords(); + var now = new DateTime.now(); + String formattedDate = DateFormat('dd-MM-yyyy').format(now); + fromdateController.text=formattedDate; + todateController.text=formattedDate; + super.initState(); + } + + Widget findings(var obj){ + return Container( + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: obj.findingsImages.length, + itemBuilder: (context, index) { + return Column( + children: [ + Card( + child: GestureDetector( + onTap: (){ + /*showPicDialog(obj.findingsImages[index]['url']);*/ + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Findings',imageDetails:obj.findingsImages[index]['url']))); + }, + child: Container( + width: MediaQuery.of(context).size.width * + .30, + height: + MediaQuery.of(context).size.height * + .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + obj.findingsImages[index]['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + ), + ), + ), + /*Expanded(child:IconButton( + icon: const Icon(Icons.remove,color: Colors.red,), + + onPressed: () async{ + + }, + ),)*/ + ], + ); + }), + ); + } + + Widget reports(var obj){ + + return Container( + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: obj.reportImages.length, + itemBuilder: (context, index) { + return Column( + children: [ + Card( + child: GestureDetector( + onTap: (){ + //showPicDialog(obj.reportImages[index]['url']); + + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Reports',imageDetails:obj.reportImages[index]['url']))); + + }, + child: Container( + width: MediaQuery.of(context).size.width * .30, + height: MediaQuery.of(context).size.height * .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + obj.reportImages[index] + ['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + ), + ), + ), + /*Expanded(child:IconButton( + icon: const Icon(Icons.remove,color: Colors.red,), + + onPressed: () async{ + + }, + ),)*/ + ], + ); + }), + ); + + } + + Widget prescriptions(var obj){ + + return Container( + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: obj.prescriptionImages.length, + itemBuilder: (context, index) { + return Column( + children: [ + Card( + child: GestureDetector( + onTap: (){ + //showPicDialog(obj.prescriptionImages[index]['url']); + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Prescriptions',imageDetails:obj.prescriptionImages[index]['url']))); + + + + }, + child: Container( + width: MediaQuery.of(context).size.width * .30, + height: MediaQuery.of(context).size.height * .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + obj.prescriptionImages[index] + ['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + ), + ), + ), + /*Expanded(child:IconButton( + icon: const Icon(Icons.remove,color: Colors.red,), + + onPressed: () async{ + + }, + ),)*/ + ], + ); + }), + ); + + } + + Widget _filtereddata(){ + if(reportsList.length!=0){ + + + + reportsList.sort((a, b) => b.date.compareTo(a.date)); + return ListView.separated( + padding: EdgeInsets.all(0), + itemCount: reportsList.length, + separatorBuilder: (context, index) { + if ((index + 1) % 2 == 0) { + return CarouselSlider( + options: CarouselOptions( + height: MediaQuery.of(context).size.height * .200, + aspectRatio: 16 / 9, + viewportFraction: 0.8, + initialPage: 0, + enableInfiniteScroll: true, + reverse: false, + autoPlay: true, + autoPlayInterval: Duration(seconds: 3), + autoPlayAnimationDuration: Duration(milliseconds: 800), + autoPlayCurve: Curves.ease, + enlargeCenterPage: true, + enlargeFactor: 0.2, + scrollDirection: Axis.horizontal, + ), + items: imgList.map((i) { + return Builder( + builder: (BuildContext context) { + return Container( + height: MediaQuery.of(context).size.height * .250, + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(0), + ), + //color: Colors.red, + child: FittedBox( + child: Image( + image: AssetImage(i), + ), + fit: BoxFit.fill, + )); + }, + ); + }).toList(), + ); + } else { + return Container(); + } + }, + itemBuilder: (BuildContext context, int index) { + if(reportsList[index].patient_type.toString().toLowerCase()=='self'){ + reportsList[index].age=widget.patAge!; + reportsList[index].gender=widget.patGender!; + reportsList[index].patient_name=widget.patName!; + } + else{ + reportsList[index].age=reportsList[index].age; + reportsList[index].gender=reportsList[index].gender; + reportsList[index].patient_name=reportsList[index].patient_name; + } + return GestureDetector( + onTap: (){ + + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new AllRecordsOnClick(recordDetails:reportsList[index],initialIndex: 0,))).then((value) { + getAllRecords(); + }); + }, + child: Card( + + //color: prescriptionsList[index].cardColor, + child: Padding( + padding:EdgeInsets.all(8) , + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + + Container( + width: MediaQuery.of(context).size.width * .55, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Problem: '+reportsList[index].problem.toString().toUpperCase(),style: problemTextStyle()), + Text(reportsList[index].doctorName.toString().toUpperCase(),style: valuesTextStyle()), + Text(reportsList[index].hospitalName.toString().toUpperCase(),style: valuesTextStyle()), + Text(reportsList[index].date.toString().toUpperCase(),style: valuesTextStyle()), + Text('Patient details: ',style: problemTextStyle()), + Text(reportsList[index].patient_name.toString().toUpperCase(),style: valuesTextStyle()), + Row( + children: [ + Text(reportsList[index].gender.toString().toUpperCase(),style: valuesTextStyle()), + SizedBox(width:MediaQuery.of(context).size.width * .05,), + Text(reportsList[index].age.toString().toUpperCase()+" Yrs",style: valuesTextStyle()), + ], + ), + + + ], + ), + + + ), + + + Expanded(child:IconButton( + icon: const Icon(Icons.edit,color: primaryColor,), + onPressed: () { + + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new UpdateReport(reportDetails:reportsList[index]))).then((value) { + getAllRecords(); + }); + }, + ),), + Expanded(child:IconButton( + icon: const Icon(Icons.delete,color: primaryColor,), + + onPressed: () async{ + showDialog( + //if set to true allow to close popup by tapping out of the popup + //barrierDismissible: false, + context: context, + builder: (BuildContext context) => AlertDialog( + title: const Text('Do you want to delete Record?', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + actionsAlignment: MainAxisAlignment.spaceBetween, + actions: [ + TextButton( + onPressed: ()async { + + bool deleteTankStatus = await AppSettings.deleteRecord(reportsList[index].recordId); + + + if(deleteTankStatus){ + getAllRecords(); + AppSettings.longSuccessToast('Record deleted successfully'); + Navigator.of(context).pop(true); + + } + else{ + AppSettings.longFailedToast('Record deletion failed'); + Navigator.of(context).pop(true); + } + }, + child: const Text('Yes', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: const Text('No', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + ], + ), + ); + + + + }, + ),) + + ], + + ), + + Row( + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async { + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new AllRecordsOnClick(recordDetails:reportsList[index],initialIndex: 0,))).then((value) { + getAllRecords(); + }); + /*Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new AllReportsTab(recordDetails:reportsList[index],initialIndex: 0,))).then((value) { + getAllRecords(); + });*/ + }, + child: Text('Findings: '+reportsList[index].findingsImages.length.toString(),style:textButtonStyleReports(),), + ), + SizedBox( + width:MediaQuery.of(context).size.width * .05, + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async { + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new AllRecordsOnClick(recordDetails:reportsList[index],initialIndex: 0,))).then((value) { + getAllRecords(); + }); + /*Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new AllReportsTab(recordDetails:reportsList[index],initialIndex: 1,))).then((value) { + getAllRecords(); + });*/ + + }, + child: Text('Reports: '+reportsList[index].reportImages.length.toString(),style:textButtonStyleReports()), + ), + SizedBox( + width:MediaQuery.of(context).size.width * .05, + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async { + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new AllRecordsOnClick(recordDetails:reportsList[index],initialIndex: 0,))).then((value) { + getAllRecords(); + }); + + /*Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new AllReportsTab(recordDetails:reportsList[index],initialIndex: 2,))).then((value) { + getAllRecords(); + });*/ + + }, + child: Text('Prescriptions: '+reportsList[index].prescriptionImages.length.toString(),style:textButtonStyleReports()), + ), + ], + ), + + + + Visibility( + visible: false, + child: Text('Findings',style: headingsTextStyle()),), + Visibility( + visible: false, + child: findings(reportsList[index])), + Visibility( + visible: false, + child: Text('Reports',style: headingsTextStyle()),), + Visibility( + visible: false, + child:reports(reportsList[index]) ), + Visibility( + visible: false, + child: Text('Prescriptions',style: headingsTextStyle()),), + Visibility( + visible:false, + child:prescriptions(reportsList[index]) ), + ], + ), + ), + ), + ); + }); + } + else{ + return Padding(padding: EdgeInsets.fromLTRB(60,10,60,10), + child: Column( + children: [ + Text('No records found related to your search'), + SizedBox( + height: 20, + ), + CircleAvatar( + backgroundColor: Colors.red, + radius: 30, + child: const Icon( + Icons.info, + color: Colors.white, + ), + ) + ], + ),); + + } + } + + + Widget _allreports(){ + + if(reportsListOriginal.length!=0){ + + return Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + /*Container( + padding: const EdgeInsets.fromLTRB(10, 10, 10, 0), + child: DropdownButtonFormField( + // Initial Value + value: dropdownSearchType, + isExpanded: true, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.search, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'Search By', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + + hint: Text('Select Search Type'), + // Down Arrow Icon + icon: const Icon(Icons.keyboard_arrow_down), + + // Array list of items + items: typeOfSearchItems.map((String items) { + return DropdownMenuItem( + value: items, + child: Text(items), + ); + }).toList(), + // After selecting the desired option,it will + // change button value to selected value + onChanged: (String? newValue) { + setState(() { + dropdownSearchType = newValue!; + }); + }, + ), + ),*/ + Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding(padding: EdgeInsets.fromLTRB(10,10,0,0), + child: Text('Please select search option',style: TextStyle(color: Colors.red,fontWeight: FontWeight.bold,fontSize: 16),),), + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: RadioListTile( + title: Text("Problem", style: TextStyle(fontSize: 10)), + value: "problem", + groupValue: searchBy, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + searchBy = value.toString(); + }); + }, + ), + ), + Expanded( + child: RadioListTile( + title: Text( + "Doctor", + style: TextStyle(fontSize: 10), + ), + value: "doctor", + groupValue: searchBy, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + searchBy = value.toString(); + }); + }, + ), + ), + Expanded( + child: RadioListTile( + title: + Text("Date", style: TextStyle(fontSize: 10)), + value: "date", + groupValue: searchBy, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + searchBy = value.toString(); + }); + }, + ), + ), + ], + ), + ], + ) + + ), + Visibility( + visible:searchBy.toString().toLowerCase()=='problem' , + child: Container( + height: MediaQuery.of(context).size.height * .07, + padding: EdgeInsets.all(5), + child: Center(child: TextField( + + cursorColor: primaryColor, + controller: searchController, + onChanged: (string) { + if(string.length>=1){ + getRecordsByProblemName(string); + } + else{ + getAllRecords(); + } + }, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.search, + color: primaryColor, + ), + /*suffixIcon: Icon( + Icons.clear, + color: greyColor, + ),*/ + suffixIcon: searchController.text!=''?IconButton( + icon: Icon( + Icons.clear, + color: Colors.red, + ), + onPressed: () { + setState(() { + searchController.text=''; + }); + getAllRecords(); + }, + ):IconButton( + icon: Icon( + Icons.clear, + color: Colors.transparent, + ), + onPressed: () { + }, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + //labelText: 'Search by phone number', + hintText: 'Search by problem', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ),) + ),), + Visibility( + visible:searchBy.toString().toLowerCase()=='doctor' , + child: Container( + height: MediaQuery.of(context).size.height * .07, + padding: EdgeInsets.all(5), + child: Center(child: TextField( + + cursorColor: primaryColor, + controller: searchController, + onChanged: (string) { + if(string.length>=1){ + getRecordsByDoctorName(string); + } + else{ + getAllRecords(); + } + }, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.search, + color: primaryColor, + ), + /*suffixIcon: Icon( + Icons.clear, + color: greyColor, + ),*/ + suffixIcon: searchController.text!=''?IconButton( + icon: Icon( + Icons.clear, + color: Colors.red, + ), + onPressed: () { + setState(() { + searchController.text=''; + }); + getAllRecords(); + }, + ):IconButton( + icon: Icon( + Icons.clear, + color: Colors.transparent, + ), + onPressed: () { + }, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + //labelText: 'Search by phone number', + hintText: 'Search by doctor', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ),) + ),), + Visibility( + visible:searchBy.toString().toLowerCase()=='date', + child: Container( + //height: 60, + padding: EdgeInsets.all(5), + child: Row( + children: [ + Expanded( + child: TextField( + + cursorColor: primaryColor, + controller: fromdateController, + onChanged: (string) { + if(string.length>=1){ + //getRecordsByDate(string); + } + else{ + getAllRecords(); + } + }, + onTap: () async { + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1950), + lastDate: DateTime.now(), + builder: (BuildContext context, Widget? child) { + return Theme( + data: ThemeData.dark().copyWith( + colorScheme: ColorScheme.dark( + primary: buttonColors, + onPrimary: Colors.white, + surface: buttonColors, + onSurface: Colors.white, + ), + dialogBackgroundColor: primaryColor, + ), + child: child!, + ); + }, + ); + + if (pickedDate != null) { + print(pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000 + String formattedDate = DateFormat('dd-MM-yyyy').format(pickedDate); + print(formattedDate); //formatted date output using intl package => 2021-03-16 + setState(() { + fromDate=pickedDate; + fromdateController.text = formattedDate; //set output date to TextField value. + }); + getRecordsByDateRange(fromdateController.text,todateController.text); + } else {} + }, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.calendar_month, + color: primaryColor, + ), + suffixIcon: fromdateController.text!=''?IconButton( + icon: Icon( + Icons.clear, + color: Colors.red, + ), + onPressed: () { + setState(() { + fromdateController.text=''; + }); + getAllRecords(); + }, + ):IconButton( + icon: Icon( + Icons.clear, + color: Colors.transparent, + ), + onPressed: () { + }, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + //labelText: 'Search by phone number', + hintText: 'From date', + + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + ), + SizedBox(width: 5), + Expanded( + child: TextField( + + cursorColor: primaryColor, + controller: todateController, + onChanged: (string) { + if(string.length>=1){ + //getRecordsByDate(string); + } + else{ + getAllRecords(); + } + }, + onTap: () async { + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: fromDate, + lastDate: DateTime.now(), + builder: (BuildContext context, Widget? child) { + return Theme( + data: ThemeData.dark().copyWith( + colorScheme: ColorScheme.dark( + primary: buttonColors, + onPrimary: Colors.white, + surface: buttonColors, + onSurface: Colors.white, + ), + dialogBackgroundColor: primaryColor, + ), + child: child!, + ); + }, + ); + + if (pickedDate != null) { + print( + pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000 + String formattedDate = + DateFormat('dd-MM-yyyy').format(pickedDate); + print( + formattedDate); //formatted date output using intl package => 2021-03-16 + setState(() { + todateController.text = formattedDate; //set output date to TextField value. + }); + getRecordsByDateRange(fromdateController.text,todateController.text); + } else {} + }, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.calendar_month, + color: primaryColor, + ), + suffixIcon: todateController.text!=''?IconButton( + icon: Icon( + Icons.clear, + color: Colors.red, + ), + onPressed: () { + setState(() { + todateController.text=''; + }); + getAllRecords(); + }, + ):IconButton( + icon: Icon( + Icons.clear, + color: Colors.transparent, + ), + onPressed: () { + }, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + //labelText: 'Search by phone number', + hintText: 'To date', + + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + ), + SizedBox(width: 5), + + ], + ), + ),), + /*Visibility( + visible:searchBy.toString().toLowerCase()=='date' , + child: Container( + height: MediaQuery.of(context).size.height * .07, + padding: EdgeInsets.all(5), + child: Center(child: TextField( + + cursorColor: primaryColor, + controller: searchController, + onChanged: (string) { + if(string.length>=1){ + getRecordsByDate(string); + } + else{ + getAllRecords(); + } + }, + onTap: () async { + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1950), + lastDate: DateTime.now(), + builder: (BuildContext context, Widget? child) { + return Theme( + data: ThemeData.dark().copyWith( + colorScheme: ColorScheme.dark( + primary: buttonColors, + onPrimary: Colors.white, + surface: buttonColors, + onSurface: Colors.white, + ), + dialogBackgroundColor: primaryColor, + ), + child: child!, + ); + }, + ); + + if (pickedDate != null) { + print( + pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000 + String formattedDate = + DateFormat('dd-MM-yyyy').format(pickedDate); + print( + formattedDate); //formatted date output using intl package => 2021-03-16 + setState(() { + searchController.text = formattedDate; //set output date to TextField value. + }); + getRecordsByDate(searchController.text); + } else {} + }, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.search, + color: primaryColor, + ), + suffixIcon: searchController.text!=''?IconButton( + icon: Icon( + Icons.clear, + color: Colors.red, + ), + onPressed: () { + setState(() { + searchController.text=''; + }); + getAllRecords(); + }, + ):IconButton( + icon: Icon( + Icons.clear, + color: Colors.transparent, + ), + onPressed: () { + }, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + //labelText: 'Search by phone number', + hintText: 'Search by date', + + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ),) + ), + + + ),*/ + Expanded(child: _filtereddata()), + + ]); + + + } + else{ + return Center( + child: Padding( + padding: EdgeInsets.fromLTRB(0, 40, 0, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox(height: MediaQuery.of(context).size.height * .25,), + Text('Click below icon to add new Record'), + SizedBox( + height: 20, + ), + CircleAvatar( + backgroundColor: primaryColor, + radius: 40, + child: IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.white, + ), + onPressed: () async { + Navigator.push(context, MaterialPageRoute(builder: (context) => AddReports(customerId:widget.customerId,patName: widget.patName,patAge: widget.patAge,patGender: widget.patGender,))).then((value) { + getAllRecords(); + }); + }, + ), + ) + ], + ), + ) + ); + } + + + } + + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppSettings.appBar('Records'), + body: isReportsDataLoading?Center( + child: CircularProgressIndicator( + color: primaryColor, + strokeWidth: 5.0, + ), + ): _allreports(), + floatingActionButton: Visibility( + visible:reportsListOriginal.length!=0, + child: CircleAvatar( + backgroundColor: buttonColors, + radius: 40, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.black, + ), + onPressed: () async{ + /*await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => AddPrescription()), + );*/ + Navigator.push(context, MaterialPageRoute(builder: (context) => AddReports(customerId:widget.customerId,patName: widget.patName,patAge: widget.patAge,patGender: widget.patGender,))).then((value) { + getAllRecords(); + }); + //showBoreAddingDialog(); + }, + ), + /* Padding( + padding: EdgeInsets.fromLTRB(5, 0, 5, 5), + child: Text( + 'Add Tanks ', + style: TextStyle(color: Colors.white), + ), + )*/ + ], + ), + ), + ), + ); + } +} diff --git a/lib/patient_dashboard/Reports/update_report.dart b/lib/patient_dashboard/Reports/update_report.dart new file mode 100644 index 0000000..8b4b592 --- /dev/null +++ b/lib/patient_dashboard/Reports/update_report.dart @@ -0,0 +1,1190 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:doctor/common/zoom_image.dart'; +import 'package:intl/intl.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:multi_image_picker/multi_image_picker.dart'; + +class UpdateReport extends StatefulWidget { + var reportDetails; + var customerId; + + UpdateReport({this.reportDetails,this.customerId}); + + @override + State createState() => _UpdateReportState(); +} + +class _UpdateReportState extends State { + TextEditingController doctorNameController = TextEditingController(); + TextEditingController hospitalNameController = TextEditingController(); + TextEditingController problemController = TextEditingController(); + TextEditingController dateInput = TextEditingController(); + TextEditingController patientNameController = TextEditingController(); + TextEditingController patientAgeController = TextEditingController(); + final ImagePicker _picker = ImagePicker(); + String Url = ''; + final ImagePicker imagePicker = ImagePicker(); + List imageFileList = []; + List imageFileListReports = []; + List imageFileListPrescriptions = []; + List uiFindingsImages = []; + List uiReportsImages = []; + List uiPrescriptionImages = []; + + List images = []; + String _error = 'No Error Dectected'; + String apiMultiImages = ''; + String? prescriptionFor; + String? gender; + + + Future pickImageFromGalleryForUpdate() async { + imageFileList = []; + final List? selectedImages = await imagePicker.pickMultiImage(); + AppSettings.preLoaderDialog(context); + if (selectedImages!.isNotEmpty) { + imageFileList.addAll(selectedImages); + } + + var res = await AppSettings.updatePrescriptionsGallery(imageFileList,widget.reportDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiPrescriptionImages = jsonDecode(res)['prescription']; + }); + } + + Future takeImageFromCameraForUpdate() async { + try { + final image = await _picker.pickImage(source: ImageSource.camera); + if (image == null) return; + final imageTemp = File(image.path); + AppSettings.preLoaderDialog(context); + var res = await AppSettings.updatePrescriptionsCamera(image,widget.reportDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiPrescriptionImages = jsonDecode(res)['prescription']; + }); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + Future pickImageFromGalleryForUpdateReports() async { + imageFileList = []; + final List? selectedImages = await imagePicker.pickMultiImage(); + AppSettings.preLoaderDialog(context); + if (selectedImages!.isNotEmpty) { + imageFileList.addAll(selectedImages); + } + + var res = await AppSettings.updateReportsGallery(imageFileList,widget.reportDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiReportsImages= jsonDecode(res)['reports']; + }); + } + + Future takeImageFromCameraForUpdateReports() async { + try { + final image = await _picker.pickImage(source: ImageSource.camera); + if (image == null) return; + final imageTemp = File(image.path); + AppSettings.preLoaderDialog(context); + var res = await AppSettings.updateReportsCamera(image,widget.reportDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiReportsImages = jsonDecode(res)['reports']; + }); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + Future pickImageFromGalleryForUpdateFindings() async { + imageFileList = []; + final List? selectedImages = await imagePicker.pickMultiImage(); + AppSettings.preLoaderDialog(context); + if (selectedImages!.isNotEmpty) { + imageFileList.addAll(selectedImages); + } + + var res = + await AppSettings.updateFindingsGallery(imageFileList, widget.reportDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiFindingsImages = jsonDecode(res)['findings']; + }); + } + + Future takeImageFromCameraForUpdateFindings() async { + try { + final image = await _picker.pickImage(source: ImageSource.camera); + if (image == null) return; + final imageTemp = File(image.path); + AppSettings.preLoaderDialog(context); + var res = await AppSettings.updateFindingsCamera(image, widget.reportDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + uiFindingsImages = jsonDecode(res)['findings']; + }); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + void detials(){ + prescriptionFor=widget.reportDetails.patient_type; + doctorNameController.text=widget.reportDetails.doctorName; + hospitalNameController.text=widget.reportDetails.hospitalName; + problemController.text = widget.reportDetails.problem; + dateInput.text = widget.reportDetails.date; + patientNameController.text =widget.reportDetails.patient_name; + patientAgeController.text = widget.reportDetails.age; + gender=widget.reportDetails.gender; + uiFindingsImages=widget.reportDetails.findingsImages; + uiReportsImages =widget.reportDetails.reportImages; + uiPrescriptionImages =widget.reportDetails.prescriptionImages; + + } + + + @override + void initState() { + + + detials(); + super.initState(); + } + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppSettings.appBar('Update Report'), + body: SingleChildScrollView( + child: Container( + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: TextFormField( + cursorColor: greyColor, + controller: doctorNameController, + textCapitalization: TextCapitalization.words, + decoration: textFormFieldDecoration( + Icons.person, 'Enter Doctor name'), + ), + ), + SizedBox( + height: MediaQuery.of(context).size.height * .02, + ), + Container( + child: TextFormField( + cursorColor: greyColor, + controller: hospitalNameController, + textCapitalization: TextCapitalization.words, + decoration: textFormFieldDecoration( + Icons.location_city_outlined, 'Enter Hospital name'), + ), + ), + SizedBox( + height: MediaQuery.of(context).size.height * .02, + ), + Container( + child: TextFormField( + cursorColor: greyColor, + controller: problemController, + textCapitalization: TextCapitalization.words, + decoration: textFormFieldDecoration( + Icons.report_problem, 'Enter Problem'), + ), + ), + SizedBox( + height: MediaQuery.of(context).size.height * .02, + ), + Container( + child: TextFormField( + cursorColor: greyColor, + controller: dateInput, + decoration: textFormFieldDecoration( + Icons.calendar_today, 'Enter Date'), + readOnly: true, + onTap: () async { + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1950), + lastDate: DateTime.now(), + builder: (BuildContext context, Widget? child) { + return Theme( + data: ThemeData.dark().copyWith( + colorScheme: ColorScheme.dark( + primary: buttonColors, + onPrimary: Colors.white, + surface: buttonColors, + onSurface: Colors.white, + ), + dialogBackgroundColor: primaryColor, + ), + child: child!, + ); + }, + ); + + if (pickedDate != null) { + print( + pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000 + String formattedDate = + DateFormat('dd-MM-yyyy').format(pickedDate); + print( + formattedDate); //formatted date output using intl package => 2021-03-16 + setState(() { + dateInput.text = + formattedDate; //set output date to TextField value. + }); + } else {} + }, + ), + ), + Row( + children: [ + Expanded( + child: RadioListTile( + title: Text("For Yourself"), + value: "self", + groupValue: prescriptionFor, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + prescriptionFor = value.toString(); + }); + }, + ), + ), + Expanded( + child: RadioListTile( + title: Text("For Family"), + value: "others", + groupValue: prescriptionFor, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + prescriptionFor = value.toString(); + }); + }, + ), + ), + ], + ), + Visibility( + visible: + prescriptionFor.toString().toLowerCase() == 'others', + child: Container( + child: TextFormField( + cursorColor: greyColor, + controller: patientNameController, + decoration: textFormFieldDecoration( + Icons.person, 'Enter patient name'), + ), + ), + ), + SizedBox( + height: MediaQuery.of(context).size.height * .02, + ), + Visibility( + visible: + prescriptionFor.toString().toLowerCase() == 'others', + child: Container( + child: TextFormField( + cursorColor: greyColor, + keyboardType: TextInputType.number, + controller: patientAgeController, + decoration: textFormFieldDecoration( + Icons.person, 'Enter patient age'), + ), + ), + ), + Visibility( + visible: + prescriptionFor.toString().toLowerCase() == 'others', + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: RadioListTile( + title: Text("Male", style: TextStyle(fontSize: 10)), + value: "male", + groupValue: gender, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + gender = value.toString(); + }); + }, + ), + ), + Expanded( + child: RadioListTile( + title: Text( + "Female", + style: TextStyle(fontSize: 10), + ), + value: "female", + groupValue: gender, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + gender = value.toString(); + }); + }, + ), + ), + Expanded( + child: RadioListTile( + title: + Text("Others", style: TextStyle(fontSize: 10)), + value: "other", + groupValue: gender, + activeColor: primaryColor, + onChanged: (value) { + setState(() { + gender = value.toString(); + }); + }, + ), + ), + ], + ), + ), + /*findings*/ + Visibility( + visible: uiFindingsImages.length == 0, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdateFindings(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdateFindings(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + child: const Text('Select Findings'), + ), + ), + Visibility( + visible: uiFindingsImages.length > 0, + child: Container( + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: uiFindingsImages.length, + itemBuilder: (context, index) { + return Column( + children: [ + Card( + child: GestureDetector( + onTap: () { + + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Findings',imageDetails:uiFindingsImages[index]['url']))); + /*gridOntap(index);*/ + }, + child: Container( + width: MediaQuery.of(context).size.width * + .30, + height: + MediaQuery.of(context).size.height * + .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + uiFindingsImages[index]['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + child: Stack(children: [ + Positioned( + right: 0, + child: Container( + child: IconButton( + iconSize: 30, + icon: const Icon( + Icons.delete, + color: Colors.red, + ), + onPressed: () async { + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) => AlertDialog( + title: + const Text('Do you want to delete image?', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + actionsAlignment: + MainAxisAlignment.spaceBetween, + actions: [ + TextButton( + onPressed: () async { + AppSettings.preLoaderDialog(context); + + + var payload = new Map(); + payload["urlType"] = 'findings'; + payload["url"] = uiFindingsImages[index]['url']; + + // bool deleteStatus = await AppSettings.deleteRecordsNew(payload,widget.recordId); + try { + var res = + await AppSettings.deleteRecordsNew( + payload, + widget.reportDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longSuccessToast( + "Image deleted Successfully"); + setState(() { + uiFindingsImages = jsonDecode(res)['remainingUrls']; + }); + } catch (e) { + print(e); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longFailedToast( + "Image deletion failed"); + } + }, + child: const Text('Yes', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: const Text('No', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + ], + ), + ); + }, + ), + ), + ) + ]), + ), + ), + ), + /*Expanded(child:IconButton( + icon: const Icon(Icons.remove,color: Colors.red,), + + onPressed: () async{ + + }, + ),)*/ + ], + ); + }), + )), + Visibility( + visible: uiFindingsImages.length != 0, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: buttonColors, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdateFindings(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdateFindings(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + child: const Text('Add Findings'), + ), + ), + + /*reports*/ + Visibility( + visible: uiReportsImages.length == 0, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdateReports(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdateReports(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + child: const Text('Select Reports'), + ), + ), + Visibility( + visible: uiReportsImages.length > 0, + child: Container( + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: uiReportsImages.length, + itemBuilder: (context, index) { + return Column( + children: [ + Card( + child: GestureDetector( + onTap: () { + + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Reports',imageDetails:uiReportsImages[index]['url']))); + /*gridOntap(index);*/ + }, + child: Container( + width: MediaQuery.of(context).size.width * + .30, + height: + MediaQuery.of(context).size.height * + .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + uiReportsImages[index]['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + child: Stack(children: [ + Positioned( + right: 0, + child: Container( + child: IconButton( + iconSize: 30, + icon: const Icon( + Icons.delete, + color: Colors.red, + ), + onPressed: () async { + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) => AlertDialog( + title: + const Text('Do you want to delete image?', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + actionsAlignment: + MainAxisAlignment.spaceBetween, + actions: [ + TextButton( + onPressed: () async { + AppSettings.preLoaderDialog(context); + + var payload = new Map(); + payload["urlType"] = 'reports'; + payload["url"] = uiReportsImages[index]['url']; + + try { + var res = + await AppSettings.deleteRecordsNew( + payload, + widget.reportDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longSuccessToast( + "Image deleted Successfully"); + setState(() { + uiReportsImages = + jsonDecode(res)['remainingUrls']; + }); + } catch (e) { + print(e); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longFailedToast( + "Image deletion failed"); + } + }, + child: const Text('Yes', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: const Text('No', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + ], + ), + ); + }, + ), + ), + ) + ]), + ), + ) + ), + /*Expanded(child:IconButton( + icon: const Icon(Icons.remove,color: Colors.red,), + + onPressed: () async{ + + }, + ),)*/ + ], + ); + }), + )), + Visibility( + visible: uiReportsImages.length != 0, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary:buttonColors, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdateReports(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdateReports(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + child: const Text('Add Reports'), + ), + ), + + /*prescriptions*/ + Visibility( + visible: uiPrescriptionImages.length == 0, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdate(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdate(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + child: const Text('Select Prescriptions'), + ), + ), + Visibility( + visible: uiPrescriptionImages.length > 0, + child: Container( + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: uiPrescriptionImages.length, + itemBuilder: (context, index) { + return Column( + children: [ + Card( + child: GestureDetector( + onTap: () { + + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Prescriptions',imageDetails:uiPrescriptionImages[index]['url']))); + /*gridOntap(index);*/ + }, + child: Container( + width: MediaQuery.of(context).size.width * + .30, + height: + MediaQuery.of(context).size.height * + .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + uiPrescriptionImages[index]['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + child: Stack(children: [ + Positioned( + right: 0, + child: Container( + child: IconButton( + iconSize: 30, + icon: const Icon( + Icons.delete, + color: Colors.red, + ), + onPressed: () async { + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) => AlertDialog( + title: + const Text('Do you want to delete image?', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + actionsAlignment: + MainAxisAlignment.spaceBetween, + actions: [ + TextButton( + onPressed: () async { + AppSettings.preLoaderDialog(context); + + + var payload = + new Map(); + payload["urlType"] = 'prescription'; + payload["url"] = uiPrescriptionImages[index]['url']; + + try { + var res = await AppSettings + .deleteRecordsNew( + payload, + widget + .reportDetails.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longSuccessToast( + "Image deleted Successfully"); + setState(() { + uiPrescriptionImages= + jsonDecode( + res)['remainingUrls']; + }); + } catch (e) { + print(e); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longFailedToast( + "Image deletion failed"); + } + }, + child: const Text('Yes', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: const Text('No', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + ], + ), + ); + }, + ), + ), + ) + ]), + ), + ) + ), + /*Expanded(child:IconButton( + icon: const Icon(Icons.remove,color: Colors.red,), + + onPressed: () async{ + + }, + ),)*/ + ], + ); + }), + )), + Visibility( + visible: uiPrescriptionImages.length != 0, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: buttonColors, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdate(); + Navigator.pop(context); + }, + ), + SizedBox( + width: + MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdate(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + child: const Text('Add Prescriptions'), + ), + ), + + /*button*/ + Container( + width: double.infinity, + height: MediaQuery.of(context).size.height * .06, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: buttonColors, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () async { + if (doctorNameController.text != '' && + problemController.text != '' && + dateInput.text != '' && + prescriptionFor != '') { + String _name = ''; + String _age = ''; + String? _gender = ''; + + if (prescriptionFor.toString().toLowerCase() == + 'others') { + if (patientNameController != '' && + patientAgeController.text != '' && + gender != '') { + _name = patientNameController.text; + _age = patientAgeController.text; + _gender = gender; + } else { + AppSettings.longFailedToast( + 'Please enter details'); + } + } else { + + } + AppSettings.preLoaderDialog(context); + bool isOnline = + await AppSettings.internetConnectivity(); + if (isOnline) { + + + var payload = new Map(); + payload["problem"] = + problemController.text.toString(); + payload["doctorName"] = + doctorNameController.text.toString(); + payload["hospitalName"] = + hospitalNameController.text.toString(); + payload["date"] = dateInput.text.toString(); + payload["findings_date"] = ''; + payload["reports_date"] = ''; + payload["prescription_date"] = ''; + payload["patientType"] = + prescriptionFor.toString(); + payload["others"] = { + "name": _name, + "age": int.parse(_age), + "gender": _gender.toString().toLowerCase() + }; + payload["findings"] = uiFindingsImages; + payload["reports"] = uiReportsImages; + payload["prescription"] = uiPrescriptionImages; + + bool uploadStatus = + await AppSettings.updateRecord(payload,widget.reportDetails.recordId); + + try { + if (uploadStatus) { + Navigator.of(context, rootNavigator: true) + .pop(); + AppSettings.longSuccessToast( + 'Record updated successfully'); + Navigator.pop(context); + } else { + Navigator.of(context, rootNavigator: true) + .pop(); + AppSettings.longFailedToast( + 'Fail to update record details'); + } + } catch (e) { + print(e); + Navigator.of(context, rootNavigator: true) + .pop(); + AppSettings.longFailedToast( + 'Fail to add record details'); + } + } else { + AppSettings.longFailedToast( + 'Please check internet'); + } + } else { + AppSettings.longFailedToast( + 'Please enter valid details'); + } + }, + child: const Text('Update Report'), + )), + ], + ), + ), + ), + )); + } +} diff --git a/lib/patient_dashboard/Sugar/sugar_calculator.dart b/lib/patient_dashboard/Sugar/sugar_calculator.dart new file mode 100644 index 0000000..cbdb755 --- /dev/null +++ b/lib/patient_dashboard/Sugar/sugar_calculator.dart @@ -0,0 +1,257 @@ +import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:doctor/patient_dashboard/Sugar/sugar_history.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:intl/intl.dart'; + + +class SugarCalculator extends StatefulWidget { + String? customerId; + SugarCalculator({this.customerId}); + + @override + State createState() => _SugarCalculatorState(); +} + +class _SugarCalculatorState extends State { + + TextEditingController fastingValueController = TextEditingController(); + TextEditingController postParandialValueController = TextEditingController(); + TextEditingController dateInput = TextEditingController(); + String sugarValue = ''; + Color sugarValueColor = Colors.black; + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppSettings.appBar('Diabetes'), + body: SingleChildScrollView( + child: Container( + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + TextFormField( + cursorColor: greyColor, + controller: fastingValueController, + textCapitalization: TextCapitalization.characters, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.person, + color: primaryColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + labelText: 'Enter fasting blood sugar value', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + SizedBox(height: 10), + TextFormField( + cursorColor: greyColor, + controller: postParandialValueController, + textCapitalization: TextCapitalization.characters, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.person, + color: primaryColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + labelText: 'Enter PostPrandial value', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + SizedBox(height: 10), + SizedBox(height: 10), + Container( + child: TextFormField( + cursorColor: greyColor, + controller: dateInput, + decoration: textFormFieldDecorationBMI( + Icons.calendar_today, 'Enter Date'), + readOnly: true, + onTap: () async { + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1950), + lastDate: DateTime.now(), + builder: (BuildContext context, Widget? child) { + return Theme( + data: ThemeData.dark().copyWith( + colorScheme: ColorScheme.dark( + primary: buttonColors, + onPrimary: Colors.white, + surface: buttonColors, + onSurface: Colors.white, + ), + dialogBackgroundColor: primaryColor, + ), + child: child!, + ); + }, + ); + + if (pickedDate != null) { + print( + pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000 + String formattedDate = + DateFormat('dd-MM-yyyy').format(pickedDate); + print( + formattedDate); //formatted date output using intl package => 2021-03-16 + setState(() { + dateInput.text = + formattedDate; //set output date to TextField value. + }); + } else {} + }, + ), + ), + SizedBox(height: 10), + Container( + width: double.infinity, + height: + MediaQuery.of(context).size.height * .05, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: buttonColors, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () async { + if (fastingValueController.text != '' && + postParandialValueController.text != ''&& dateInput.text!='') { + + if(int.parse(fastingValueController.text)>int.parse(postParandialValueController.text)){ + AppSettings.longFailedToast('Please enter post parandial value is higher than fasting blood sugar value details'); + } + else{ + AppSettings.preLoaderDialog(context); + var payload = new Map(); + + payload["fasting"] = double.parse(fastingValueController.text.toString()); + payload["postPrandial"] = double.parse(postParandialValueController.text.toString()); + payload["date"] = dateInput.text.toString(); + + var value = await AppSettings.calculateSugar(payload,widget.customerId); + var valueResponse = jsonDecode(value); + print(valueResponse); + setState(() { + sugarValue = valueResponse['userSugarDetails']['sugarCategory'].toString(); + if(sugarValue.toUpperCase().toUpperCase()=='VERY HIGH BLOOD SUGAR'){ + sugarValueColor=Colors.red; + } + else if(sugarValue.toUpperCase().toUpperCase()=='HIGH BLOOD SUGAR'){ + sugarValueColor=Colors.red; + } + else if(sugarValue.toUpperCase().toUpperCase()=='PREDIABETES (IMPAIRED FASTING GLUCOSE)'){ + sugarValueColor=Colors.red; + } + else if(sugarValue.toUpperCase().toUpperCase()=='VERY LOW BLOOD SUGAR'){ + sugarValueColor=Colors.red; + } + else if(sugarValue.toUpperCase().toUpperCase()=='LOW BLOOD SUGAR'){ + sugarValueColor=Colors.red; + } + else if(sugarValue.toUpperCase().toUpperCase()=='NORMAL BLOOD SUGAR (HEALTHY RANGE)'){ + sugarValueColor=buttonColors; + } + + }); + fastingValueController.clear(); + postParandialValueController.clear(); + dateInput.clear(); + Navigator.of(context,rootNavigator: true).pop(); + } + + + } + else{ + AppSettings.longFailedToast('Please enter valid details'); + } + }, + child: const Text('Check Diabetes'), + )), + SizedBox(height: 10), + Container( + child: Row( + children: [ + Text(sugarValue,style: TextStyle(color: sugarValueColor,fontWeight: FontWeight.bold,fontSize: 20),), + Visibility( + visible:sugarValue!='' , + child: Icon( + Icons.emoji_emotions_outlined, + color: buttonColors, + size: 40, + ),) + ], + ) + ), + SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + children: [ + IconButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => SugarHistory(customerId: widget.customerId,)), + ); + }, + icon: Icon( + Icons.history, + color: primaryColor, + size: 40, + ), + ), + SizedBox(height: 10), + Padding(padding: EdgeInsets.fromLTRB(10,0,0,0), + child: Container( + child: Text('History',style:TextStyle(color:Colors.black,fontSize: 12,fontWeight: FontWeight.bold,)), + ),) + ], + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + primary: buttonColors, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () async { + Navigator.pop(context); + }, + child: const Text('Cancel'), + ) + ], + ) + + + ], + ), + ) + ), + ) + ); + } +} diff --git a/lib/patient_dashboard/Sugar/sugar_history.dart b/lib/patient_dashboard/Sugar/sugar_history.dart new file mode 100644 index 0000000..d8685ee --- /dev/null +++ b/lib/patient_dashboard/Sugar/sugar_history.dart @@ -0,0 +1,354 @@ +import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:doctor/patient_dashboard/Sugar/sugar_calculator.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:doctor/models/sugar_history_model.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; + +class SugarHistory extends StatefulWidget { + String? customerId; + SugarHistory({this.customerId}); + + @override + State createState() => _SugarHistoryState(); +} + +class _SugarHistoryState extends State { + bool isLoading = false; + List sugarHistoryList = []; + List FilteredList = []; + var dateItems = [ + 'All', + 'last 7 days', + 'last one month', + 'last one year', + ]; + var dateItemsVariable = 'All'; + + Future getSugarHistoryDetails(var selectedRange) async { + isLoading = true; + var response1 = await AppSettings.getSugarHistory(widget.customerId); + print(response1); + setState(() { + sugarHistoryList = ((jsonDecode(response1)) as List).map((dynamic model) { + return SugarHistoryModel.fromJson(model); + }).toList(); + + var now = new DateTime.now(); + var now_1w = now.subtract(Duration(days: 7)); + var now_1m = new DateTime(now.year, now.month - 1, now.day); + var now_1y = new DateTime(now.year - 1, now.month, now.day); + + if (selectedRange.toString().toUpperCase() == 'LAST 7 DAYS') { + FilteredList = sugarHistoryList.where((product) { + final date = product.dateForFilter; + return now_1w.isBefore(date); + }).toList(); + } else if (selectedRange.toString().toUpperCase() == 'LAST ONE MONTH') { + FilteredList = sugarHistoryList.where((product) { + final date = product.dateForFilter; + return now_1m.isBefore(date); + }).toList(); + } else if (selectedRange.toString().toUpperCase() == 'LAST ONE YEAR') { + FilteredList = sugarHistoryList.where((product) { + final date = product.dateForFilter; + return now_1y.isBefore(date); + }).toList(); + } else { + FilteredList = sugarHistoryList; + } + + isLoading = false; + }); + } + + @override + void initState() { + getSugarHistoryDetails(dateItemsVariable); + super.initState(); + } + + deleteSugarRecord(sugarInfoId) async { + AppSettings.preLoaderDialog(context); + bool status = await AppSettings.deleteSugarDetails(sugarInfoId,widget.customerId); + + if (status) { + Navigator.of(context, rootNavigator: true).pop(); + + AppSettings.longSuccessToast("BP record deleted successfully"); + await getSugarHistoryDetails(dateItemsVariable); + } else { + Navigator.of(context, rootNavigator: true).pop(); + + AppSettings.longFailedToast("BP record deletion failed"); + } + } + + Widget renderzUi() { + if (FilteredList.length != 0) { + FilteredList.sort((a, b) => b.actualDate.compareTo(a.actualDate)); + return Column(crossAxisAlignment: CrossAxisAlignment.end, children: [ + Padding( + padding: EdgeInsets.fromLTRB(10, 10, 10, 10), + child: DropdownButtonFormField( + // Initial Value + value: dateItemsVariable, + isExpanded: true, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.calendar_month, + color: primaryColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + labelText: 'Select Date Range', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + + hint: Text('Units'), + // Down Arrow Icon + //icon: const Icon(Icons.keyboard_arrow_down), + + // Array list of items + items: dateItems.map((String items) { + return DropdownMenuItem( + value: items, + child: Text( + items, + style: TextStyle( + fontSize: 16, + ), + textAlign: TextAlign.center, + )); + }).toList(), + // After selecting the desired option,it will + // change button value to selected value + onChanged: (String? newValue) { + setState(() { + dateItemsVariable = newValue!; + }); + getSugarHistoryDetails(dateItemsVariable); + }, + ), + ), + Expanded( + child: ListView.builder( + padding: EdgeInsets.all(0), + itemCount: FilteredList.length, + itemBuilder: (BuildContext context, int index) { + return Slidable( + key: const ValueKey(0), + endActionPane: ActionPane( + // A motion is a widget used to control how the pane animates. + motion: ScrollMotion(), + + dragDismissible: false, + // A pane can dismiss the Slidable. + dismissible: DismissiblePane(onDismissed: () { + deleteSugarRecord(FilteredList[index].sugarInfoId); + }), + + // All actions are defined in the children parameter. + children: [ + // A SlidableAction can have an icon and/or a label. + SlidableAction( + backgroundColor: Color(0xFFFE4A49), + foregroundColor: Colors.white, + icon: Icons.delete, + label: 'Delete', + onPressed: (BuildContext context) { + deleteSugarRecord(FilteredList[index].sugarInfoId); + }, + ), + ], + ), + child: Card( + color: Colors.white, + child: Padding( + padding: EdgeInsets.all(8), + child: + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Fasting Sugar Value', + style: labelTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + 'PostPrandial Sugar Value', + style: labelTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + 'Sugar Status', + style: labelTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + 'Date', + style: labelTextStyle(), + ), + ], + ), + SizedBox(width:MediaQuery.of(context).size.width * .01,), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + ':', + style: labelTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + ':', + style: labelTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + ':', + style: labelTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + ':', + style: labelTextStyle(), + ), + ], + ), + SizedBox(width:MediaQuery.of(context).size.width * .01,), + Expanded(child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + FilteredList[index] + .fasting + .toString() + .toUpperCase(), + style: valuesTextStyle()), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + FilteredList[index] + .postPrandial + .toString() + .toUpperCase(), + style: valuesTextStyle()), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + FilteredList[index] + .sugartText + .toString() + .toUpperCase(), + style: TextStyle( + color: FilteredList[index] + .sugarValueColor, + fontSize: 12, + fontWeight: FontWeight.bold, + overflow: TextOverflow.ellipsis, + )), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + FilteredList[index] + .actualDate + .toString() + .toUpperCase(), + style: valuesTextStyle()), + ], + ),) + ], + ), + ), + )); + })), + ]); + } else { + return Center( + child: Padding( + padding: EdgeInsets.fromLTRB(0, 40, 0, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + height: MediaQuery.of(context).size.height * .25, + ), + Text('No data'), + SizedBox( + height: 20, + ), + CircleAvatar( + backgroundColor: primaryColor, + radius: 40, + child: IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.white, + ), + onPressed: () async { + Navigator.push(context, MaterialPageRoute(builder: (context) => SugarCalculator(customerId:widget.customerId))).then((value) { + getSugarHistoryDetails(dateItemsVariable); + }); + }, + ), + ) + ], + ), + )); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppSettings.appBar('Diabetes'), + body: isLoading + ? Center( + child: CircularProgressIndicator( + color: primaryColor, + strokeWidth: 5.0, + ), + ) + : renderzUi(), + floatingActionButton: Visibility( + visible:FilteredList.length!=0, + child: CircleAvatar( + backgroundColor: buttonColors, + radius: 40, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.black, + ), + onPressed: () async { + Navigator.push(context, MaterialPageRoute(builder: (context) => SugarCalculator(customerId: widget.customerId,))).then((value) { + getSugarHistoryDetails(dateItemsVariable); + }); + }, + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/patient_dashboard/patient_dashboard.dart b/lib/patient_dashboard/patient_dashboard.dart new file mode 100644 index 0000000..cbdf2f6 --- /dev/null +++ b/lib/patient_dashboard/patient_dashboard.dart @@ -0,0 +1,159 @@ +import 'package:doctor/common/settings.dart'; +import 'package:doctor/patient_dashboard/patient_dshboard_details.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart'; +import 'package:flutter/services.dart'; + +class PatientDashboard extends StatefulWidget { + const PatientDashboard({Key? key}) : super(key: key); + + @override + State createState() => _PatientDashboardState(); +} + +class _PatientDashboardState extends State { + + bool isScannerVisible=true; + TextEditingController mobileNumberController = TextEditingController(); + final List images = [ + 'https://via.placeholder.com/150', + 'https://via.placeholder.com/150', + 'https://via.placeholder.com/150', + 'https://via.placeholder.com/150', + 'https://via.placeholder.com/150', + 'https://via.placeholder.com/150', + 'https://via.placeholder.com/150', + 'https://via.placeholder.com/150', + 'https://via.placeholder.com/150', + ]; + + + Future scanQR() async { + String barcodeScanRes; + // Platform messages may fail, so we use a try/catch PlatformException. + try { + barcodeScanRes = await FlutterBarcodeScanner.scanBarcode( + '#ff6666', 'Cancel', true, ScanMode.QR); + print(barcodeScanRes); + setState(() { + + }); + } on PlatformException { + barcodeScanRes = 'Failed to get platform version.'; + }} + + + Future onWillPop() async { + final shouldPop = await showDialog(context: context, builder: (context) { + return AlertDialog( + title: const Text('Do you want to leave this page', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + actionsAlignment: MainAxisAlignment.spaceBetween, + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: const Text('Yes', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(false); + }, + child: const Text('No', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + ], + ); + }, + ); + return shouldPop!; + } + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async => onWillPop(), + child: Scaffold( + appBar: AppSettings.appBar('Patient Dashboard'), + body: SafeArea( + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + children: [ + SizedBox( + height:MediaQuery.of(context).size.height * .02, + ), + Visibility( + visible: isScannerVisible, + child:Center( + child: Container( + + child: Column( + children: [ + IconButton( + onPressed: (){ + scanQR(); + }, + icon: Icon( + Icons.qr_code_scanner, + color: primaryColor, + ), + ), + Text('Scan Qr Code',style: TextStyle(fontSize: 12,color: primaryColor),) + ], + ) + ), + ), + ), + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Container( + child: TextFormField( + cursorColor: primaryColor, + controller: mobileNumberController, + keyboardType: TextInputType.number, + textCapitalization: TextCapitalization.characters, + decoration: textFormFieldDecorationInsideApp(Icons.phone,'Enter mobile number'), + ), + ), + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Container( + width:double.infinity, + height: MediaQuery.of(context).size.height * .06, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: buttonColors, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async { + if(mobileNumberController.text!=''){ + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PatientDashboardDetails(mobileNumber: mobileNumberController.text.toString(),)), + ); + } + else{ + AppSettings.longFailedToast('Please enter details'); + } + }, + child: Text('Go to details'), + )), + + + ] + ))) ) ), + ); + + } +} diff --git a/lib/patient_dashboard/patient_dshboard_details.dart b/lib/patient_dashboard/patient_dshboard_details.dart new file mode 100644 index 0000000..2a571ef --- /dev/null +++ b/lib/patient_dashboard/patient_dshboard_details.dart @@ -0,0 +1,245 @@ +import 'dart:convert'; + +import 'package:doctor/common/settings.dart'; +import 'package:doctor/patient_dashboard/BMI/bmi_history.dart'; +import 'package:doctor/patient_dashboard/BP/bp_history.dart'; +import 'package:doctor/patient_dashboard/Reports/allreports.dart'; +import 'package:doctor/patient_dashboard/Sugar/sugar_history.dart'; +import 'package:doctor/patient_dashboard/prescriptions/prescriptions.dart'; +import 'package:doctor/patient_dashboard/problems/all_problems.dart'; +import 'package:flutter/material.dart'; + +class PatientDashboardDetails extends StatefulWidget { + String? mobileNumber; + PatientDashboardDetails({this.mobileNumber}); + + @override + State createState() => _PatientDashboardDetailsState(); +} + +class _PatientDashboardDetailsState extends State { + + bool isDataLoading=false; + bool isSereverIssue=false; + String? customerId; + String? patientName; + String? patientAge; + String? patientGender; + String? patientContactNumber; + final List images = [ + 'images/bp.png', + 'images/sugar.png', + 'images/bmi.png', + 'images/health_records.png', + 'images/prescriptions.png', + 'images/medicines.png', + 'images/new_problem.png', + 'images/get_checkup.png', + 'images/resources.png', + ]; + final List labels = [ + 'Bp', + 'Sugar', + 'BMI', + 'Health Records', + 'Prescriptions', + 'Medicines', + 'New Problem', + 'Get Checkup', + 'Resources', + ]; + Map patDetails={}; + + Future getPatientInformation() async { + isDataLoading=true; + try { + var response = await AppSettings.getPatientInformationBasedOnMobileNumber(widget.mobileNumber); + print(jsonDecode(response)); + setState(() { + customerId=jsonDecode(response)[0]['customerId']; + patientName=jsonDecode(response)[0]['profile']['firstName']; + patientAge=jsonDecode(response)[0]['age'].toString(); + patientGender=jsonDecode(response)[0]['gender']; + patientContactNumber=jsonDecode(response)[0]['profile']['contactNumber']; + isDataLoading = false; + }); + } catch (e) { + setState(() { + isDataLoading = false; + isSereverIssue = true; + }); + } + } + + @override + void initState() { + getPatientInformation(); + super.initState(); + } + + + _onTap(int index){ + if(index==0){ + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => BPHistory(customerId:customerId,)), + ); + } + else if(index==1){ + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => SugarHistory(customerId:customerId,)), + ); + } + else if(index==2){ + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => BMIHistory(customerId:customerId,)), + ); + } + else if(index==3){ + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => AllReports(customerId:customerId,patName: patientName,patAge: patientAge,patGender: patientGender,)), + ); + } + else if(index==4){ + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => Prescriptions(customerId:customerId,patName: patientName,patAge: patientAge,patGender: patientGender,)), + ); + } + else if(index==6){ + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => AllProblemsReportMyself(customerId:customerId,patName: patientName,patAge: patientAge,patGender: patientGender,)), + ); + } + else if(index==7){ + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => AllProblemsReportMyself(customerId:customerId,patName: patientName,patAge: patientAge,patGender: patientGender,)), + ); + } + } + + +Widget _dashboard(){ + return Column( + children: [ + Padding(padding: EdgeInsets.all(10), + child: Align(child: Text('Patient Information',style: TextStyle(color: primaryColor,fontSize: 16),), + alignment: Alignment.topLeft),), + Padding(padding: EdgeInsets.all(10), + child: Card(child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Name'), + Text('Age'), + Text('Gender'), + Text('Contact Number') + ], + ), + SizedBox( + width:MediaQuery.of(context).size.width * .02, + ), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(':'), + Text(':'), + Text(':'), + Text(':') + ], + ), + SizedBox( + width:MediaQuery.of(context).size.width * .02, + ), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(patientName!), + Text(patientAge!), + Text(patientGender!), + Text(patientContactNumber!) + ], + ), + ], + ),),), + Expanded(child: Container( + + child: Padding( + padding: EdgeInsets.all(10), + child: GridView.builder( + itemCount: images.length, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, + crossAxisSpacing: 4.0, + mainAxisSpacing: 4.0, + ), + itemBuilder: (BuildContext context, int index) { + return GestureDetector( + onTap: () { + _onTap(index); + }, + child: Column( + children: [ + Expanded(child: Container( + decoration: BoxDecoration( + color: secondaryColor, + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(30), + image: DecorationImage( + image: AssetImage(images[index],) , // picked file + fit: BoxFit.fitWidth)), + //color: secondaryColor, + + )), + Padding(padding: EdgeInsets.all(10), + child: Text(labels[index]),), + /*Divider( + color: Colors.grey, + height: 1.0, + ),*/ + ], + ) + ); + }, + ), + ) + )) + ], + ); +} + + + @override + Widget build(BuildContext context) { + return Scaffold( + + appBar: AppSettings.appBar('Patient Dashboard Details'), + body: Container( + child: isDataLoading?Center( + child: CircularProgressIndicator( + color: primaryColor, + strokeWidth: 5.0, + ), + ): _dashboard(), + ), + ); + } +} diff --git a/lib/patient_dashboard/prescriptions/add_prescriptions.dart b/lib/patient_dashboard/prescriptions/add_prescriptions.dart new file mode 100644 index 0000000..ed66213 --- /dev/null +++ b/lib/patient_dashboard/prescriptions/add_prescriptions.dart @@ -0,0 +1,418 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:doctor/patient_dashboard/prescriptions/prescriptions.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:photo_view/photo_view.dart'; +import 'package:pinch_zoom/pinch_zoom.dart'; + +class AddPrescription extends StatefulWidget { + String? customerId; + String? patName; + String? patAge; + String? patGender; + AddPrescription({this.customerId,this.patName,this.patAge,this.patGender}); + + + @override + State createState() => _AddPrescriptionState(); +} + +class _AddPrescriptionState extends State { + + final ImagePicker _picker = ImagePicker(); + String Url = ''; + final _transformationController = TransformationController(); + TapDownDetails _doubleTapDetails=TapDownDetails(); + TextEditingController prescriptionNameController = TextEditingController(); + TextEditingController patientNameController = TextEditingController(); + TextEditingController patientAgeController = TextEditingController(); + String? prescriptionFor; + String? gender; + + Future pickImageFromGallery() async { + try { + final image = await _picker.pickImage(source: ImageSource.gallery); + if (image == null) return; + final imageTemp = File(image.path); + + AppSettings.preLoaderDialog(context); + var res = await AppSettings.uploadImageHTTPForPrescriptions(image,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + Url = jsonDecode(res)['pictures'][0]; + }); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + Future takeImageFromCamera() async { + try { + final image = await _picker.pickImage(source: ImageSource.camera); + if (image == null) return; + final imageTemp = File(image.path); + AppSettings.preLoaderDialog(context); + var res = await AppSettings.uploadImageHTTPForPrescriptions(image,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + Url = jsonDecode(res)['pictures'][0]; + }); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + Widget zoomPhoto(var imageUrl){ + return Container( + width: MediaQuery.of(context).size.width * .18, + height: MediaQuery.of(context).size.height * .10, + child: PhotoView( + imageProvider: NetworkImage(imageUrl) as ImageProvider, + ) + ); + } + + + showPicDialog(var imageUrl){ + return showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + return AlertDialog( + title: const Text(''), + content: SingleChildScrollView( + child: ListBody( + children: [ + Container( + width: MediaQuery.of(context).size.width * .10, + height: MediaQuery.of(context).size.height * .50, + child: PhotoView( + imageProvider: NetworkImage(imageUrl) as ImageProvider, + maxScale: PhotoViewComputedScale.contained * 4.0, + minScale: PhotoViewComputedScale.contained, + initialScale: PhotoViewComputedScale.contained, + basePosition: Alignment.center, + + ) + ) + ], + ), + ), + actions: [ + TextButton( + child: Text('Close', style: textButtonStyle()), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }); + }, + ); + } + + void _handleDoubleTap() { + if (_transformationController.value != Matrix4.identity()) { + _transformationController.value = Matrix4.identity(); + } else { + final position = _doubleTapDetails.localPosition; + // For a 3x zoom + _transformationController.value = Matrix4.identity() + ..translate(-position.dx * 2, -position.dy * 2) + ..scale(3.0); + // Fox a 2x zoom + // ..translate(-position.dx, -position.dy) + // ..scale(2.0); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppSettings.appBar('Add Prescription'), + body:SingleChildScrollView( + child: Container( + child: Padding( + padding: EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCamera(); + Navigator.pop(context); + }, + ), + SizedBox( + width: MediaQuery.of(context).size.width * .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGallery(); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + }, + child: const Text('Select image'), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Visibility( + visible: Url != '', + child: GestureDetector( + child: + /*,*/ + /*Container( + width: MediaQuery.of(context).size.width * .18, + height: MediaQuery.of(context).size.height * .10, + child: PhotoView( + imageProvider: NetworkImage(Url) as ImageProvider, + maxScale: PhotoViewComputedScale.contained * 4.0, + minScale: PhotoViewComputedScale.contained, + initialScale: PhotoViewComputedScale.contained, + basePosition: Alignment.center, + + ) + ),*/ + Container( + width: MediaQuery.of(context).size.width * .18, + height: MediaQuery.of(context).size.height * .10, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage(Url) as ImageProvider, // picked file + fit: BoxFit.fill)), + ), + onTap: (){ + showPicDialog(Url); + }, + ) + ), + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Container( + child: TextFormField( + cursorColor: greyColor, + controller: prescriptionNameController, + decoration: textFormFieldDecoration(Icons.edit,'Enter Prescription name'), + + ), + ), + Row( + children: [ + + Expanded(child: RadioListTile( + title: Text("For Yourself"), + value: "self", + groupValue: prescriptionFor, + activeColor: primaryColor, + onChanged: (value){ + setState(() { + prescriptionFor = value.toString(); + }); + }, + ),), + Expanded(child: RadioListTile( + title: Text("For Family"), + value: "others", + groupValue: prescriptionFor, + activeColor: primaryColor, + onChanged: (value){ + setState(() { + prescriptionFor = value.toString(); + }); + }, + ),), + ], + ), + Visibility( + visible:prescriptionFor.toString().toLowerCase()=='others' , + child: Container( + child: TextFormField( + cursorColor: greyColor, + controller: patientNameController, + decoration: textFormFieldDecoration(Icons.person,'Enter patient name'), + + ), + ),), + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Visibility( + visible:prescriptionFor.toString().toLowerCase()=='others' , + child: Container( + child: TextFormField( + cursorColor: greyColor, + keyboardType: TextInputType.number, + controller: patientAgeController, + decoration: textFormFieldDecoration(Icons.person,'Enter patient age'), + + ), + ),), + Visibility( + visible:prescriptionFor.toString().toLowerCase()=='others' , + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + + Expanded(child: RadioListTile( + title: Text("Male",style: TextStyle(fontSize: 10)), + value: "male", + groupValue: gender, + activeColor: primaryColor, + onChanged: (value){ + setState(() { + gender = value.toString(); + }); + }, + ),), + Expanded(child: RadioListTile( + title: Text("Female",style: TextStyle(fontSize: 10),), + value: "female", + groupValue: gender, + activeColor: primaryColor, + onChanged: (value){ + setState(() { + gender = value.toString(); + }); + }, + ),), + Expanded(child: RadioListTile( + title: Text("Others",style: TextStyle(fontSize: 10)), + value: "other", + groupValue: gender, + activeColor: primaryColor, + onChanged: (value){ + setState(() { + gender = value.toString(); + }); + }, + ),), + ], + ),), + SizedBox(height:MediaQuery.of(context).size.height * .02,), + Container( + width:double.infinity, + height: MediaQuery.of(context).size.height * .06, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: buttonColors, // background + onPrimary: Colors.black, // foreground + ), + onPressed: () async{ + if(Url!=''&& prescriptionNameController.text!=''&&prescriptionFor!=''){ + + String _name=''; + String _age=''; + String? _gender=''; + + if(prescriptionFor.toString().toLowerCase()=='others'){ + if(patientNameController!=''&& patientAgeController.text!=''&&gender!=''){ + _name=patientNameController.text; + _age=patientAgeController.text; + _gender=gender; + } + else{ + AppSettings.longFailedToast('Please enter details'); + } + } + else{ + _name=widget.patName!; + _age=widget.patAge!; + _gender=widget.patGender!; + } + AppSettings.preLoaderDialog(context); + bool isOnline = await AppSettings.internetConnectivity(); + if(isOnline){ + var payload = new Map(); + payload["name"] = prescriptionNameController.text.toString(); + payload["pictureUrl"] = Url.toString(); + payload["patientType"] = prescriptionFor.toString(); + payload["others"] ={ + "name": _name, + "age": int.parse(_age), + "gender": _gender.toString().toLowerCase() + }; + bool uploadStatus = await AppSettings.addPrescription(payload,widget.customerId); + + try{ + if(uploadStatus){ + Navigator.of(context,rootNavigator: true).pop(); + AppSettings.longSuccessToast('Prescription added successfully'); + Navigator.pop(context); + /* await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => Prescriptions()), + );*/ + } + else{ + Navigator.of(context,rootNavigator: true).pop(); + AppSettings.longFailedToast('Fail to add prescription details'); + } + } + catch(e){ + print(e); + Navigator.of(context,rootNavigator: true).pop(); + AppSettings.longFailedToast('Fail to add prescription details'); + } + + + } + else{ + AppSettings.longFailedToast('Please check internet'); + } + } + else{ + AppSettings.longFailedToast('Please upload image'); + } + + + }, + child: const Text('Upload'), + )), + + + ], + ), + )) , + ) + ); + } +} diff --git a/lib/patient_dashboard/prescriptions/prescriptions.dart b/lib/patient_dashboard/prescriptions/prescriptions.dart new file mode 100644 index 0000000..bf5da82 --- /dev/null +++ b/lib/patient_dashboard/prescriptions/prescriptions.dart @@ -0,0 +1,976 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:doctor/patient_dashboard//Reports/add_reports.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:doctor/common/zoom_image.dart'; +import 'package:doctor/models/reports_model.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:photo_view/photo_view.dart'; +import 'package:intl/intl.dart'; + +class Prescriptions extends StatefulWidget { + String? customerId; + String? patName; + String? patAge; + String? patGender; + Prescriptions({this.customerId,this.patName,this.patAge,this.patGender}); + + @override + State createState() => _PrescriptionsState(); +} + +class _PrescriptionsState extends State { + final ImagePicker _picker = ImagePicker(); + String Url = ''; + List reportsList = []; + List reportsListOriginal = []; + bool isPharmacyDataLoading = false; + bool isPrescriptionsDataLoading = false; + bool isSereverIssue = false; + double lat = 0; + double lng = 0; + String userAddress = ''; + String dropdownArea = '2'; + var AreaItems = ['2', '5', '10', '25', '50', '100']; + List pharmaciesCheckboxes = []; + bool isLoading=false; + final ImagePicker imagePicker = ImagePicker(); + List imageFileList = []; + List uiPrescriptionImages = []; + TextEditingController searchController = TextEditingController(); + TextEditingController dateInput = TextEditingController(); + String dropdownSearchType = 'Problem'; + var typeOfSearchItems = [ + 'Problem', + 'Doctor', + 'Date', + ]; + + + + Future getAllRecords() async { + isPrescriptionsDataLoading=true; + try { + var response = await AppSettings.getAllRecords(widget.customerId); + + setState(() { + reportsListOriginal = ((jsonDecode(response)) as List) + .map((dynamic model) { + return ReportsModel.fromJson(model); + }).toList(); + reportsList=reportsListOriginal.reversed.toList(); + isPrescriptionsDataLoading = false; + }); + } catch (e) { + setState(() { + isPrescriptionsDataLoading = false; + isSereverIssue = true; + }); + } + } + + Future getRecordsByProblemName(var problem) async { + + isPrescriptionsDataLoading=true; + try { + var response = await AppSettings.getAllRecords(widget.customerId); + + setState(() { + reportsListOriginal = ((jsonDecode(response)) as List) + .map((dynamic model) { + return ReportsModel.fromJson(model); + }).toList(); + reportsList=reportsListOriginal.reversed.toList(); + reportsList= reportsListOriginal.where( + (x) => x.problem.toString().toLowerCase().contains(problem.toString().toLowerCase()) + ).toList(); + isPrescriptionsDataLoading = false; + }); + } catch (e) { + setState(() { + isPrescriptionsDataLoading = false; + isSereverIssue = true; + }); + } + } + + Future getRecordsByDoctorName(var doctor) async { + + isPrescriptionsDataLoading=true; + try { + var response = await AppSettings.getAllRecords(widget.customerId); + + setState(() { + reportsListOriginal = ((jsonDecode(response)) as List) + .map((dynamic model) { + return ReportsModel.fromJson(model); + }).toList(); + reportsList=reportsListOriginal.reversed.toList(); + reportsList= reportsListOriginal.where( + (x) => x.doctorName.toString().toLowerCase().contains(doctor.toString().toLowerCase()) + ).toList(); + isPrescriptionsDataLoading = false; + }); + } catch (e) { + setState(() { + isPrescriptionsDataLoading = false; + isSereverIssue = true; + }); + } + } + + Future getRecordsByDate(var date) async { + + isPrescriptionsDataLoading=true; + try { + var response = await AppSettings.getAllRecords(widget.customerId); + + setState(() { + reportsListOriginal = ((jsonDecode(response)) as List) + .map((dynamic model) { + return ReportsModel.fromJson(model); + }).toList(); + reportsList=reportsListOriginal.reversed.toList(); + reportsList= reportsListOriginal.where( + (x) => x.date.toString().toLowerCase().contains(date.toString().toLowerCase()) + ).toList(); + isPrescriptionsDataLoading = false; + }); + } catch (e) { + setState(() { + isPrescriptionsDataLoading = false; + isSereverIssue = true; + }); + } + } + + @override + void initState() { + getAllRecords(); + super.initState(); + } + + Future pickImageFromGallery() async { + try { + final image = await _picker.pickImage(source: ImageSource.gallery); + if (image == null) return; + final imageTemp = File(image.path); + + AppSettings.preLoaderDialog(context); + var res = await AppSettings.uploadImageHTTPForPrescriptions(image,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + Url = jsonDecode(res)['pictures'][0]; + }); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + Future takeImageFromCamera() async { + try { + final image = await _picker.pickImage(source: ImageSource.camera); + if (image == null) return; + final imageTemp = File(image.path); + AppSettings.preLoaderDialog(context); + var res = await AppSettings.uploadImageHTTPForPrescriptions(image,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + setState(() { + Url = jsonDecode(res)['pictures'][0]; + }); + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + + Future pickImageFromGalleryForUpdate(var recordId) async { + imageFileList = []; + final List? selectedImages = await imagePicker.pickMultiImage(); + AppSettings.preLoaderDialog(context); + if (selectedImages!.isNotEmpty) { + imageFileList.addAll(selectedImages); + } + + var res = await AppSettings.updatePrescriptionsGallery(imageFileList,recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + getAllRecords(); + } + + Future takeImageFromCameraForUpdate(var recordId) async { + try { + final image = await _picker.pickImage(source: ImageSource.camera); + if (image == null) return; + final imageTemp = File(image.path); + AppSettings.preLoaderDialog(context); + var res = await AppSettings.updatePrescriptionsCamera(image,recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + getAllRecords(); + + } on PlatformException catch (e) { + print('Failed to pick image: $e'); + } + } + + + showPicDialog(var imageUrl){ + return showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + return AlertDialog( + title: const Text(''), + content: SingleChildScrollView( + child: ListBody( + children: [ + Container( + width: MediaQuery.of(context).size.width * .10, + height: MediaQuery.of(context).size.height * .50, + child: PhotoView( + imageProvider: NetworkImage(imageUrl) as ImageProvider, + maxScale: PhotoViewComputedScale.contained * 4.0, + minScale: PhotoViewComputedScale.contained, + initialScale: PhotoViewComputedScale.contained, + basePosition: Alignment.center, + + ) + ) + ], + ), + ), + actions: [ + TextButton( + child: Text('Close', style: textButtonStyle()), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }); + }, + ); + } + + Widget prescriptions(var obj){ + if(obj.prescriptionImages.length!=0){ + return Container( + //color: secondaryColor, + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: Row( + children: [ + Expanded(child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: obj.prescriptionImages.length, + itemBuilder: (context, index) { + return Row( + children: [ + Card( + child: GestureDetector( + onTap: (){ + //showPicDialog(obj.prescriptionImages[index]['url']); + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Prescriptions',imageDetails:obj.prescriptionImages[index]['url'])));}, + child: Container( + width: MediaQuery.of(context).size.width * .30, + height: MediaQuery.of(context).size.height * .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + obj.prescriptionImages[index]['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + child: Stack(children: [ + Positioned( + right: 0, + child: Container( + child: IconButton( + iconSize: 30, + icon: const Icon( + Icons.delete, + color: Colors.red, + ), + onPressed: () async { + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) => AlertDialog( + title: + const Text('Do you want to delete image?', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + actionsAlignment: + MainAxisAlignment.spaceBetween, + actions: [ + TextButton( + onPressed: () async { + AppSettings.preLoaderDialog(context); + + String fileName = obj.prescriptionImages[index]['url'] + .split('/') + .last; + + var payload = + new Map(); + payload["urlType"] = 'prescription'; + payload["url"] = obj.prescriptionImages[index]['url']; + + try { + var res = await AppSettings.deleteRecordsNew(payload, obj.recordId,widget.customerId); + print(jsonDecode(res)); + Navigator.of(context, rootNavigator: true).pop(); + Navigator.of(context).pop(true); + AppSettings.longSuccessToast("Image deleted Successfully"); + setState(() { + obj.prescriptionImages = + jsonDecode( + res)['remainingUrls']; + }); + } catch (e) { + print(e); + Navigator.of(context, + rootNavigator: true) + .pop(); + Navigator.of(context).pop(true); + AppSettings.longFailedToast( + "Image deletion failed"); + } + }, + child: const Text('Yes', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: const Text('No', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + ], + ), + ); + }, + ), + ), + ) + ]), + ), + ), + ) + + ], + ); + }),), + IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.green, + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdate(obj.recordId); + Navigator.pop(context); + }, + ), + SizedBox( + width: MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdate(obj.recordId); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + + + + }, + ) + + ], + ) + ); + } + else{ + return Row( + children: [ + IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.green, + ), + onPressed: () async { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return SizedBox( + height: 200, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: Icon( + Icons.camera_alt_outlined, + size: 100, + color: primaryColor, + ), + onTap: () async { + await takeImageFromCameraForUpdate(obj.recordId); + Navigator.pop(context); + }, + ), + SizedBox( + width: MediaQuery.of(context).size.width * + .20, + ), + GestureDetector( + child: Icon( + Icons.photo, + size: 100, + color: primaryColor, + ), + onTap: () async { + await pickImageFromGalleryForUpdate(obj.recordId); + Navigator.pop(context); + }, + ), + ], + ), + ), + ); + }); + + + + }, + ), + Text('Add Prescriptions',style: textButtonStyle(),) + ], + ); + } + + + + } + + Widget _filtereddata(){ + if (reportsList.length != 0) { + return Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded(child:ListView.builder( + padding: EdgeInsets.all(0), + itemCount: reportsList.length, + itemBuilder: (BuildContext context, int index) { + if(reportsList[index].patient_type.toString().toLowerCase()=='self'){ + reportsList[index].age=widget.patAge!; + reportsList[index].gender=widget.patGender!; + reportsList[index].patient_name=widget.patName!; + } + else{ + reportsList[index].age=reportsList[index].age; + reportsList[index].gender=reportsList[index].gender; + reportsList[index].patient_name=reportsList[index].patient_name; + } + + return Visibility( + visible: true, + child: Card( + + //color: prescriptionsList[index].cardColor, + child: Padding( + padding:EdgeInsets.all(8) , + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + + Container( + width: MediaQuery.of(context).size.width * .55, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Problem: '+reportsList[index].problem.toString().toUpperCase(),style: problemTextStyle()), + Text(reportsList[index].doctorName.toString().toUpperCase(),style: valuesTextStyle()), + Text(reportsList[index].hospitalName.toString().toUpperCase(),style: valuesTextStyle()), + Text(reportsList[index].date.toString().toUpperCase(),style: valuesTextStyle()), + Text('Patient Details: ',style: problemTextStyle()), + Text(reportsList[index].patient_name.toString().toUpperCase(),style: valuesTextStyle()), + Row( + children: [ + Text(reportsList[index].gender.toString().toUpperCase(),style: valuesTextStyle()), + SizedBox(width:MediaQuery.of(context).size.width * .05,), + Text(reportsList[index].age.toString().toUpperCase()+" Yrs",style: valuesTextStyle()), + ], + ), + + + ], + ), + + + ), + ], + + ), + + SizedBox(height:MediaQuery.of(context).size.height * .02,), + + prescriptions(reportsList[index]), + + ], + ), + ), + )); + }) ), + ]); + } + else{ + return Padding(padding: EdgeInsets.fromLTRB(60,10,60,10), + child: Column( + children: [ + Text('No prescriptions found related to your search'), + SizedBox( + height: 20, + ), + CircleAvatar( + backgroundColor: Colors.red, + radius: 30, + child: const Icon( + Icons.info, + color: Colors.white, + ), + ) + ], + ),); + } + } + + Widget _allPrescriptions(){ + + if(reportsListOriginal.length!=0){ + + return Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Container( + padding: const EdgeInsets.fromLTRB(10, 10, 10, 0), + child: DropdownButtonFormField( + // Initial Value + value: dropdownSearchType, + isExpanded: true, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.search, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'Search By', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + + hint: Text('Select Search Type'), + // Down Arrow Icon + icon: const Icon(Icons.keyboard_arrow_down), + + // Array list of items + items: typeOfSearchItems.map((String items) { + return DropdownMenuItem( + value: items, + child: Text(items), + ); + }).toList(), + // After selecting the desired option,it will + // change button value to selected value + onChanged: (String? newValue) { + setState(() { + dropdownSearchType = newValue!; + }); + }, + ), + ), + Visibility( + visible:dropdownSearchType.toString().toLowerCase()=='problem' , + child: Container( + height: MediaQuery.of(context).size.height * .07, + padding: EdgeInsets.all(5), + child: Center(child: TextField( + + cursorColor: primaryColor, + controller: searchController, + onChanged: (string) { + if(string.length>=1){ + getRecordsByProblemName(string); + } + else{ + getAllRecords(); + } + }, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.search, + color: primaryColor, + ), + /*suffixIcon: Icon( + Icons.clear, + color: greyColor, + ),*/ + suffixIcon: searchController.text!=''?IconButton( + icon: Icon( + Icons.clear, + color: Colors.red, + ), + onPressed: () { + setState(() { + searchController.text=''; + }); + getAllRecords(); + }, + ):IconButton( + icon: Icon( + Icons.clear, + color: Colors.transparent, + ), + onPressed: () { + }, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + //labelText: 'Search by phone number', + hintText: 'Search by problem', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ),) + ),), + Visibility( + visible:dropdownSearchType.toString().toLowerCase()=='doctor' , + child: Container( + height: MediaQuery.of(context).size.height * .07, + padding: EdgeInsets.all(5), + child: Center(child: TextField( + + cursorColor: primaryColor, + controller: searchController, + onChanged: (string) { + if(string.length>=1){ + getRecordsByDoctorName(string); + } + else{ + getAllRecords(); + } + }, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.search, + color: primaryColor, + ), + /*suffixIcon: Icon( + Icons.clear, + color: greyColor, + ),*/ + suffixIcon: searchController.text!=''?IconButton( + icon: Icon( + Icons.clear, + color: Colors.red, + ), + onPressed: () { + setState(() { + searchController.text=''; + }); + getAllRecords(); + }, + ):IconButton( + icon: Icon( + Icons.clear, + color: Colors.transparent, + ), + onPressed: () { + }, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + //labelText: 'Search by phone number', + hintText: 'Search by doctor', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ),) + ),), + Visibility( + visible:dropdownSearchType.toString().toLowerCase()=='date' , + child: Container( + height: MediaQuery.of(context).size.height * .07, + padding: EdgeInsets.all(5), + child: Center(child: TextField( + + cursorColor: primaryColor, + controller: searchController, + onChanged: (string) { + if(string.length>=1){ + getRecordsByDate(string); + } + else{ + getAllRecords(); + } + }, + onTap: () async { + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1950), + lastDate: DateTime.now(), + builder: (BuildContext context, Widget? child) { + return Theme( + data: ThemeData.dark().copyWith( + colorScheme: ColorScheme.dark( + primary: buttonColors, + onPrimary: Colors.white, + surface: buttonColors, + onSurface: Colors.white, + ), + dialogBackgroundColor: primaryColor, + ), + child: child!, + ); + }, + ); + + if (pickedDate != null) { + print( + pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000 + String formattedDate = + DateFormat('dd-MM-yyyy').format(pickedDate); + print( + formattedDate); //formatted date output using intl package => 2021-03-16 + setState(() { + searchController.text = formattedDate; //set output date to TextField value. + }); + getRecordsByDate(searchController.text); + } else {} + }, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.search, + color: primaryColor, + ), + suffixIcon: searchController.text!=''?IconButton( + icon: Icon( + Icons.clear, + color: Colors.red, + ), + onPressed: () { + setState(() { + searchController.text=''; + }); + getAllRecords(); + }, + ):IconButton( + icon: Icon( + Icons.clear, + color: Colors.transparent, + ), + onPressed: () { + }, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + //labelText: 'Search by phone number', + hintText: 'Search by date', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ),) + ), + + + ), + Expanded(child: _filtereddata()), + Padding( + padding: EdgeInsets.fromLTRB(8, 8, 8, 8), + child: CircleAvatar( + backgroundColor: primaryColor, + radius: 40, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.white, + ), + onPressed: () async{ + /*await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => AddPrescription()), + );*/ + Navigator.push(context, MaterialPageRoute(builder: (context) => AddReports(customerId:widget.customerId,patName: widget.patName,patAge: widget.patAge,patGender: widget.patGender,))).then((value) { + getAllRecords(); + }); + //showBoreAddingDialog(); + }, + ), + /* Padding( + padding: EdgeInsets.fromLTRB(5, 0, 5, 5), + child: Text( + 'Add Tanks ', + style: TextStyle(color: Colors.white), + ), + )*/ + ], + ), + ), + ), + ]); + + + } + else{ + return Center( + child: Padding( + padding: EdgeInsets.fromLTRB(0, 40, 0, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox(height: MediaQuery.of(context).size.height * .25,), + Text('Click below icon to add new Record'), + SizedBox( + height: 20, + ), + CircleAvatar( + backgroundColor: primaryColor, + radius: 40, + child: IconButton( + iconSize: 40, + icon: const Icon( + Icons.add, + color: Colors.white, + ), + onPressed: () async { + Navigator.push(context, MaterialPageRoute(builder: (context) => AddReports(customerId:widget.customerId,patName: widget.patName,patAge: widget.patAge,patGender: widget.patGender,))).then((value) { + getAllRecords(); + }); + }, + ), + ) + ], + ), + ) + ); + } + + + } + + /**/ + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppSettings.appBar('Prescriptions'), + body: isPrescriptionsDataLoading?Center( + child: CircularProgressIndicator( + color: primaryColor, + strokeWidth: 5.0, + ), + ): _allPrescriptions(), + ); + } +} diff --git a/lib/patient_dashboard/problems/all_problems.dart b/lib/patient_dashboard/problems/all_problems.dart new file mode 100644 index 0000000..25fda6b --- /dev/null +++ b/lib/patient_dashboard/problems/all_problems.dart @@ -0,0 +1,1058 @@ +import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:doctor/common/settings.dart'; +import 'package:doctor/common/zoom_image.dart'; +import 'package:doctor/models/all_problems_model.dart'; +import 'package:doctor/patient_dashboard/problems/video_file.dart'; +import 'package:photo_view/photo_view.dart'; +import 'package:intl/intl.dart'; +import 'package:flutter_sound/flutter_sound.dart'; +import 'package:assets_audio_player/assets_audio_player.dart'; + +class AllProblemsReportMyself extends StatefulWidget { + String? customerId; + String? patName; + String? patAge; + String? patGender; + AllProblemsReportMyself({this.customerId,this.patName,this.patAge,this.patGender}); + + @override + State createState() => _AllProblemsReportMyselfState(); +} + +class _AllProblemsReportMyselfState extends State { + + + List allProblemsList = []; + List allProblemsListOriginal = []; + bool isProblemDataLoading = false; + bool isSereverIssue = false; + TextEditingController searchController = TextEditingController(); + TextEditingController dateInput = TextEditingController(); + TextEditingController fromdateController = TextEditingController(); + TextEditingController todateController = TextEditingController(); + String dropdownSearchType = 'All'; + bool isAudioButtonPressed=false; + bool _playAudio=false; + final recordingPlayer = AssetsAudioPlayer(); + var typeOfSearchItems = [ + 'All', + 'Problem', + 'Date', + ]; + + Future getAllProblemsReportMyself() async { + isProblemDataLoading=true; + try { + var response = await AppSettings.getAllReportProblemDetalis(widget.customerId); + + setState(() { + allProblemsListOriginal = ((jsonDecode(response)) as List) + .map((dynamic model) { + return AllProblemsModel.fromJson(model); + }).toList(); + allProblemsList=allProblemsListOriginal.reversed.toList(); + isProblemDataLoading = false; + }); + } catch (e) { + setState(() { + isProblemDataLoading = false; + isSereverIssue = true; + }); + } + } + + Future getAllProblemsReportMyselfByProblem(var problem) async { + + isProblemDataLoading=true; + try { + var response = await AppSettings.getAllReportProblemDetalis(widget.customerId); + + setState(() { + allProblemsListOriginal = ((jsonDecode(response)) as List) + .map((dynamic model) { + return AllProblemsModel.fromJson(model); + }).toList(); + allProblemsList=allProblemsListOriginal.reversed.toList(); + allProblemsList= allProblemsListOriginal.where( + (x) => x.problem.toString().toLowerCase().contains(problem.toString().toLowerCase()) + ).toList(); + isProblemDataLoading = false; + }); + } catch (e) { + setState(() { + isProblemDataLoading = false; + isSereverIssue = true; + }); + } + } + + + Future getAllProblemsReportMyselfByDateRange(var fromDate,var toDate) async { + isProblemDataLoading = true; + + try { + var response = await AppSettings.getAllReportProblemDetalis(widget.customerId); + + setState(() { + allProblemsListOriginal = ((jsonDecode(response)) as List) + .map((dynamic model) { + return AllProblemsModel.fromJson(model); + }).toList(); + allProblemsList=allProblemsListOriginal.reversed.toList(); + var dateToCheck = DateTime.now().add(Duration(days: -1)); + + allProblemsList = allProblemsListOriginal.where((product) { + final date = product.dateForFilter; + final startDate =DateFormat('dd-MM-yyyy').parse(fromDate); + final endDate = DateFormat('dd-MM-yyyy').parse(toDate); + return date.isAfter(startDate) && date.isBefore(endDate); + //reportsList=reportsListOriginal.reversed.toList(); + }).toList(); + + /*if( dateToCheck.isAfter(startDate) && dateToCheck.isBefore(endDate)) + { + print("dateToCheck is between now and lastYear"); + } + else + { + print("dateToCheck is not between now and lastYear"); + }*/ + + + isProblemDataLoading = false; + }); + } catch (e) { + setState(() { + isProblemDataLoading = false; + isSereverIssue = true; + }); + } + } + + + @override + void initState() { + getAllProblemsReportMyself(); + var now = new DateTime.now(); + String formattedDate = DateFormat('dd-MM-yyyy').format(now); + fromdateController.text=formattedDate; + todateController.text=formattedDate; + super.initState(); + } + + + showPicDialog(var imageUrl){ + return showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + return AlertDialog( + title: const Text(''), + content: SingleChildScrollView( + child: ListBody( + children: [ + Container( + width: MediaQuery.of(context).size.width * .10, + height: MediaQuery.of(context).size.height * .50, + child: PhotoView( + imageProvider: NetworkImage(imageUrl) as ImageProvider, + maxScale: PhotoViewComputedScale.contained * 4.0, + minScale: PhotoViewComputedScale.contained, + initialScale: PhotoViewComputedScale.contained, + basePosition: Alignment.center, + + ) + ) + ], + ), + ), + actions: [ + TextButton( + child: Text('Close', style: textButtonStyle()), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }); + }, + ); + } + + + Widget findings(var obj){ + return Container( + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: obj.findingsImages.length, + itemBuilder: (context, index) { + return Column( + children: [ + Card( + child: GestureDetector( + onTap: (){ + /*showPicDialog(obj.findingsImages[index]['url']);*/ + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Findings',imageDetails:obj.findingsImages[index]['url']))); + }, + child: Container( + width: MediaQuery.of(context).size.width * + .30, + height: + MediaQuery.of(context).size.height * + .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + obj.findingsImages[index]['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + ), + ), + ), + /*Expanded(child:IconButton( + icon: const Icon(Icons.remove,color: Colors.red,), + + onPressed: () async{ + + }, + ),)*/ + ], + ); + }), + ); + } + + Widget reports(var obj){ + + return Container( + width: double.infinity, + height: MediaQuery.of(context).size.height * .20, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: obj.reportImages.length, + itemBuilder: (context, index) { + return Column( + children: [ + Card( + child: GestureDetector( + onTap: (){ + //showPicDialog(obj.reportImages[index]['url']); + + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Reports',imageDetails:obj.reportImages[index]['url']))); + + }, + child: Container( + width: MediaQuery.of(context).size.width * .30, + height: MediaQuery.of(context).size.height * .15, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + image: DecorationImage( + image: NetworkImage( + obj.reportImages[index] + ['url']) + as ImageProvider, // picked file + fit: BoxFit.fill)), + ), + ), + ), + /*Expanded(child:IconButton( + icon: const Icon(Icons.remove,color: Colors.red,), + + onPressed: () async{ + + }, + ),)*/ + ], + ); + }), + ); + + } + + + + Future playFunc(var audio) async { + recordingPlayer.open( + Audio.file(audio), + autoStart: true, + showNotification: true, + ); + } + + Future stopPlayFunc() async { + recordingPlayer.stop(); + } + + Widget _filtereddata(){ + if(allProblemsList.length!=0){ + return ListView.builder( + itemCount: allProblemsList.length, + itemBuilder: (BuildContext context, int index) { + return GestureDetector( + onTap: (){ + + }, + child: Card( + + //color: prescriptionsList[index].cardColor, + child: Padding( + padding:EdgeInsets.all(8) , + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + + Container( + width: MediaQuery.of(context).size.width * .60, + child: + Column( + children: [ + Row( + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Problem', + style: labelTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + 'Description', + style: labelTextStyle(), + ), + + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + 'Date', + style: labelTextStyle(), + ), + ], + ), + SizedBox(width:MediaQuery.of(context).size.width * .01,), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + ':', + style: labelTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + ':', + style: labelTextStyle(), + ), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + ':', + style: labelTextStyle(), + ), + ], + ), + SizedBox(width:MediaQuery.of(context).size.width * .01,), + Expanded(child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + allProblemsList[index] + .problem + .toString() + .toUpperCase(), + style: valuesTextStyle()), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + allProblemsList[index].description + .toString() + .toUpperCase(), + style: valuesTextStyle()), + SizedBox(height:MediaQuery.of(context).size.height * .01,), + Text( + allProblemsList[index] + .date + .toString() + .toUpperCase(), + style: valuesTextStyle()), + ], + ),) + ], + ), + Row( + children: [ + Visibility( + visible: allProblemsList[index].audio!='', + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async { + setState(() { + + + if(!allProblemsList[index].isAudioButtonEnabled){ + setState(() { + allProblemsList[index].isAudioButtonEnabled=true; + }); + } + else{ + setState(() { + allProblemsList[index].isAudioButtonEnabled=false; + }); + } + }); + }, + child: const Text('Audio'), + ),), + Visibility( + visible: allProblemsList[index].audio!='', + child: SizedBox( + width:MediaQuery.of(context).size.width * .01, + ) ,), + Visibility( + visible: allProblemsList[index].video!='', + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async { + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ProblemVideo(videoUrl:allProblemsList[index].video))); + + }, + child: const Text('Video'), + ),), + + Visibility( + visible: allProblemsList[index].video!='', + child: SizedBox( + width:MediaQuery.of(context).size.width * .01, + ) ,), + Visibility( + visible: allProblemsList[index].image!='', + child: ElevatedButton( + style: ElevatedButton.styleFrom( + primary: primaryColor, // background + onPrimary: Colors.white, // foreground + ), + onPressed: () async { + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new ImageZoomPage(imageName:'Problem Picture',imageDetails:allProblemsList[index].image))); + + }, + child: const Text('Image'), + ),), + + ], + ), + Visibility( + visible: allProblemsList[index].isAudioButtonEnabled, + child:Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + ElevatedButton.icon( + style: + ElevatedButton.styleFrom(elevation: 9.0, primary: Colors.red), + onPressed: () { + setState(() { + _playAudio = !_playAudio; + }); + if (_playAudio) playFunc(allProblemsList[index].audio); + if (!_playAudio) stopPlayFunc(); + }, + icon: _playAudio + ? Icon( + Icons.stop, + ) + : Icon(Icons.play_arrow), + label: _playAudio + ? Text( + "Stop", + style: TextStyle( + fontSize: 28, + ), + ) + : Text( + "Play", + style: TextStyle( + fontSize: 28, + ), + ), + ), + ], + ) + ) + + ], + ) + ), + + + Visibility( + visible:false, + child: Expanded(child:IconButton( + icon: const Icon(Icons.edit,color: primaryColor,), + onPressed: () { + + /*Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new UpdateReport(reportDetails:allProblemsList[index]))).then((value) { + getAllProblemsReportMyself(); + });*/ + }, + ),), + ), + /*Expanded(child:IconButton( + icon: const Icon(Icons.delete,color: primaryColor,), + + onPressed: () async{ + showDialog( + //if set to true allow to close popup by tapping out of the popup + //barrierDismissible: false, + context: context, + builder: (BuildContext context) => AlertDialog( + title: const Text('Do you want to delete Record?', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + actionsAlignment: MainAxisAlignment.spaceBetween, + actions: [ + TextButton( + onPressed: ()async { + + bool deleteTankStatus = await AppSettings.deleteReportMySelfProblem(allProblemsList[index].problemId); + + + if(deleteTankStatus){ + getAllProblemsReportMyself(); + AppSettings.longSuccessToast('Problem deleted successfully'); + Navigator.of(context).pop(true); + + } + else{ + AppSettings.longFailedToast('Problem deletion failed'); + Navigator.of(context).pop(true); + } + }, + child: const Text('Yes', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: const Text('No', + style: TextStyle( + color: primaryColor, + fontSize: 20, + )), + ), + ], + ), + ); + + + + }, + ),)*/ + + ], + + ), + + ], + ), + ), + ), + ); + }); + } + else{ + return Padding(padding: EdgeInsets.fromLTRB(60,10,60,10), + child: Column( + children: [ + Text('No problems found related to your search'), + SizedBox( + height: 20, + ), + CircleAvatar( + backgroundColor: Colors.red, + radius: 30, + child: const Icon( + Icons.info, + color: Colors.white, + ), + ) + ], + ),); + + } + } + + + Widget _allreports(){ + + if(allProblemsListOriginal.length!=0){ + + return Padding(padding:EdgeInsets.all(10), + child:Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Container( + child: DropdownButtonFormField( + // Initial Value + value: dropdownSearchType, + isExpanded: true, + decoration: const InputDecoration( + prefixIcon: Icon( + Icons.search, + color: greyColor, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: greyColor)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: greyColor), + ), + labelText: 'Search By', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + + hint: Text('Select Search Type'), + // Down Arrow Icon + icon: const Icon(Icons.keyboard_arrow_down), + + // Array list of items + items: typeOfSearchItems.map((String items) { + return DropdownMenuItem( + value: items, + child: Text(items), + ); + }).toList(), + // After selecting the desired option,it will + // change button value to selected value + onChanged: (String? newValue) { + setState(() { + dropdownSearchType = newValue!; + }); + }, + ), + ), + SizedBox(height: MediaQuery.of(context).size.height * .01,), + Visibility( + visible:dropdownSearchType.toString().toLowerCase()=='problem' , + child: Container( + height: MediaQuery.of(context).size.height * .07, + child: Center(child: TextField( + + cursorColor: primaryColor, + controller: searchController, + onChanged: (string) { + if(string.length>=1){ + getAllProblemsReportMyselfByProblem(string); + } + else{ + getAllProblemsReportMyself(); + } + }, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.search, + color: primaryColor, + ), + /*suffixIcon: Icon( + Icons.clear, + color: greyColor, + ),*/ + suffixIcon: searchController.text!=''?IconButton( + icon: Icon( + Icons.clear, + color: Colors.red, + ), + onPressed: () { + setState(() { + searchController.text=''; + }); + getAllProblemsReportMyself(); + }, + ):IconButton( + icon: Icon( + Icons.clear, + color: Colors.transparent, + ), + onPressed: () { + }, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + //labelText: 'Search by phone number', + hintText: 'Search by problem', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ),) + ),), + Visibility( + visible:dropdownSearchType.toString().toLowerCase()=='doctor' , + child: Container( + height: MediaQuery.of(context).size.height * .07, + child: Center(child: TextField( + + cursorColor: primaryColor, + controller: searchController, + onChanged: (string) { + if(string.length>=1){ + //getRecordsByDoctorName(string); + } + else{ + getAllProblemsReportMyself(); + } + }, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.search, + color: primaryColor, + ), + /*suffixIcon: Icon( + Icons.clear, + color: greyColor, + ),*/ + suffixIcon: searchController.text!=''?IconButton( + icon: Icon( + Icons.clear, + color: Colors.red, + ), + onPressed: () { + setState(() { + searchController.text=''; + }); + getAllProblemsReportMyself(); + }, + ):IconButton( + icon: Icon( + Icons.clear, + color: Colors.transparent, + ), + onPressed: () { + }, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + //labelText: 'Search by phone number', + hintText: 'Search by doctor', + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ),) + ),), + Visibility( + visible:dropdownSearchType.toString().toLowerCase()=='date', + child: Container( + //height: 60, + child: Row( + children: [ + Expanded( + child: TextField( + + cursorColor: primaryColor, + controller: fromdateController, + onChanged: (string) { + if(string.length>=1){ + //getRecordsByDate(string); + } + else{ + getAllProblemsReportMyself(); + } + }, + onTap: () async { + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1950), + lastDate: DateTime.now(), + builder: (BuildContext context, Widget? child) { + return Theme( + data: ThemeData.dark().copyWith( + colorScheme: ColorScheme.dark( + primary: buttonColors, + onPrimary: Colors.white, + surface: buttonColors, + onSurface: Colors.white, + ), + dialogBackgroundColor: primaryColor, + ), + child: child!, + ); + }, + ); + + if (pickedDate != null) { + print( + pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000 + String formattedDate = + DateFormat('dd-MM-yyyy').format(pickedDate); + print( + formattedDate); //formatted date output using intl package => 2021-03-16 + setState(() { + fromdateController.text = formattedDate; //set output date to TextField value. + }); + getAllProblemsReportMyselfByDateRange(fromdateController.text,todateController.text); + } else {} + }, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.calendar_month, + color: primaryColor, + ), + suffixIcon: fromdateController.text!=''?IconButton( + icon: Icon( + Icons.clear, + color: Colors.red, + ), + onPressed: () { + setState(() { + fromdateController.text=''; + }); + getAllProblemsReportMyself(); + }, + ):IconButton( + icon: Icon( + Icons.clear, + color: Colors.transparent, + ), + onPressed: () { + }, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + //labelText: 'Search by phone number', + hintText: 'From date', + + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + ), + SizedBox(width: 5), + Expanded( + child: TextField( + + cursorColor: primaryColor, + controller: todateController, + onChanged: (string) { + if(string.length>=1){ + //getRecordsByDate(string); + } + else{ + getAllProblemsReportMyself(); + } + }, + onTap: () async { + DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(1950), + lastDate: DateTime.now(), + builder: (BuildContext context, Widget? child) { + return Theme( + data: ThemeData.dark().copyWith( + colorScheme: ColorScheme.dark( + primary: buttonColors, + onPrimary: Colors.white, + surface: buttonColors, + onSurface: Colors.white, + ), + dialogBackgroundColor: primaryColor, + ), + child: child!, + ); + }, + ); + + if (pickedDate != null) { + print( + pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000 + String formattedDate = + DateFormat('dd-MM-yyyy').format(pickedDate); + print( + formattedDate); //formatted date output using intl package => 2021-03-16 + setState(() { + todateController.text = formattedDate; //set output date to TextField value. + }); + getAllProblemsReportMyselfByDateRange(fromdateController.text,todateController.text); + } else {} + }, + decoration: InputDecoration( + prefixIcon: Icon( + Icons.calendar_month, + color: primaryColor, + ), + suffixIcon: todateController.text!=''?IconButton( + icon: Icon( + Icons.clear, + color: Colors.red, + ), + onPressed: () { + setState(() { + todateController.text=''; + }); + getAllProblemsReportMyself(); + }, + ):IconButton( + icon: Icon( + Icons.clear, + color: Colors.transparent, + ), + onPressed: () { + }, + ), + border: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: primaryColor), + borderRadius: BorderRadius.circular(30), + ), + //labelText: 'Search by phone number', + hintText: 'To date', + + labelStyle: TextStyle( + color: greyColor, //<-- SEE HERE + ), + ), + ), + ), + SizedBox(width: 5), + + ], + ), + ),), + Expanded(child: _filtereddata()), + ])); + + + } + else{ + return Center( + child: Padding( + padding: EdgeInsets.fromLTRB(0, 40, 0, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox(height: MediaQuery.of(context).size.height * .25,), + Text('No Data found'), + SizedBox( + height: 20, + ), + CircleAvatar( + backgroundColor: primaryColor, + radius: 40, + child: IconButton( + iconSize: 40, + icon: const Icon( + Icons.info, + color: Colors.white, + ), + onPressed: () async { + /*Navigator.push(context, MaterialPageRoute(builder: (context) => ReportMySelf())).then((value) { + getAllProblemsReportMyself(); + });*/ + }, + ), + ) + ], + ), + ) + ); + } + + + } + + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppSettings.appBar('New Problems'), + body: isProblemDataLoading?Center( + child: CircularProgressIndicator( + color: primaryColor, + strokeWidth: 5.0, + ), + ): _allreports(), + ); + } +} + diff --git a/lib/patient_dashboard/problems/video_file.dart b/lib/patient_dashboard/problems/video_file.dart new file mode 100644 index 0000000..88d7269 --- /dev/null +++ b/lib/patient_dashboard/problems/video_file.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; +import 'package:video_player/video_player.dart'; +import 'package:flick_video_player/flick_video_player.dart'; + +class ProblemVideo extends StatefulWidget { + var videoUrl; + ProblemVideo({this.videoUrl}); + + @override + State createState() => _ProblemVideoState(); +} + +class _ProblemVideoState extends State { + + late VideoPlayerController _controller; + late Future _initializeVideoPlayerFuture; + late FlickManager flickManager; + + @override + void initState() { + super.initState(); + _controller = VideoPlayerController.networkUrl( + Uri.parse(widget.videoUrl,), + ); + flickManager = FlickManager( + videoPlayerController: + VideoPlayerController.networkUrl(Uri.parse(widget.videoUrl,),) + ); + _initializeVideoPlayerFuture = _controller.initialize(); + _controller.setLooping(false); + } + @override + void dispose() { + // Ensure disposing of the VideoPlayerController to free up resources. + _controller.dispose(); + flickManager.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + height: MediaQuery.of(context).size.height * .30, + width: double.infinity, + child:FlickVideoPlayer( + flickManager: flickManager, + flickVideoWithControls: FlickVideoWithControls( + videoFit: BoxFit.fill, + controls: FlickPortraitControls( + progressBarSettings: + FlickProgressBarSettings(playedColor: Colors.green), + ), + ), + + ), + + ); + } +} diff --git a/lib/video_call/video_call.dart b/lib/video_call/video_call.dart new file mode 100644 index 0000000..fbad608 --- /dev/null +++ b/lib/video_call/video_call.dart @@ -0,0 +1,19 @@ +import 'package:doctor/common/settings.dart'; +import 'package:flutter/material.dart'; + +class VideoCall extends StatefulWidget { + const VideoCall({Key? key}) : super(key: key); + + @override + State createState() => _VideoCallState(); +} + +class _VideoCallState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppSettings.appBar('Video Call'), + body: Container(), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 56010e5..9f33314 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -370,6 +370,13 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_barcode_scanner: + dependency: "direct main" + description: + name: flutter_barcode_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" flutter_cupertino_datetime_picker: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 09f4875..7fd4a28 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -61,6 +61,7 @@ dependencies: flutter_launcher_icons: ^0.11.0 share: ^2.0.4 flutter_share: ^2.0.0 + flutter_barcode_scanner: ^2.0.0 dev_dependencies: flutter_test: