diff --git a/android/app/build.gradle b/android/app/build.gradle index ae87782e..da345fc2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -44,6 +44,7 @@ android { versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + multiDexEnabled true } buildTypes { @@ -72,9 +73,10 @@ dependencies { implementation 'com.opentok.android:opentok-android-sdk:2.16.5' //permissions implementation 'pub.devrel:easypermissions:0.4.0' - +implementation 'com.google.firebase:firebase-core:9.6.1' //retrofit implementation 'com.squareup.retrofit2:retrofit:2.6.2' implementation 'com.squareup.retrofit2:converter-gson:2.6.2' implementation 'com.squareup.okhttp3:logging-interceptor:3.14.1' + apply plugin: 'com.google.gms.google-services' } diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 00000000..3c00f05c --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,39 @@ +{ + "project_info": { + "project_number": "1008895414777", + "project_id": "doctorapp-9f172", + "storage_bucket": "doctorapp-9f172.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:1008895414777:android:d00fe21d6955c21b1f6d28", + "android_client_info": { + "package_name": "com.example.doctor_app_flutter" + } + }, + "oauth_client": [ + { + "client_id": "1008895414777-3mg88j5ocs5r1au7rf4sh3f4pgsri2f2.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyCNncEIj8ehVUSxV89rx0x1NaWp8t1YVkw" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "1008895414777-3mg88j5ocs5r1au7rf4sh3f4pgsri2f2.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle index 357c6a1a..ea0f0026 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,6 +8,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.5.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath 'com.google.gms:google-services:4.3.2' } } diff --git a/android/google-services.json b/android/google-services.json new file mode 100644 index 00000000..3c00f05c --- /dev/null +++ b/android/google-services.json @@ -0,0 +1,39 @@ +{ + "project_info": { + "project_number": "1008895414777", + "project_id": "doctorapp-9f172", + "storage_bucket": "doctorapp-9f172.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:1008895414777:android:d00fe21d6955c21b1f6d28", + "android_client_info": { + "package_name": "com.example.doctor_app_flutter" + } + }, + "oauth_client": [ + { + "client_id": "1008895414777-3mg88j5ocs5r1au7rf4sh3f4pgsri2f2.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyCNncEIj8ehVUSxV89rx0x1NaWp8t1YVkw" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "1008895414777-3mg88j5ocs5r1au7rf4sh3f4pgsri2f2.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/gradle.properties b/android/gradle.properties index 38c8d454..9c0729c9 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,4 +1,5 @@ -org.gradle.jvmargs=-Xmx1536M + android.enableR8=true android.useAndroidX=true android.enableJetifier=true +org.gradle.jvmargs=-Xmx4608m diff --git a/assets/images/login/101.png b/assets/images/login/101.png new file mode 100644 index 00000000..90c1c575 Binary files /dev/null and b/assets/images/login/101.png differ diff --git a/assets/images/login/102.png b/assets/images/login/102.png new file mode 100644 index 00000000..8502d197 Binary files /dev/null and b/assets/images/login/102.png differ diff --git a/assets/images/login/103.png b/assets/images/login/103.png new file mode 100644 index 00000000..3326814b Binary files /dev/null and b/assets/images/login/103.png differ diff --git a/assets/images/login/104.png b/assets/images/login/104.png new file mode 100644 index 00000000..ad55ff74 Binary files /dev/null and b/assets/images/login/104.png differ diff --git a/assets/images/login/fileNum.png b/assets/images/login/fileNum.png new file mode 100644 index 00000000..386299b7 Binary files /dev/null and b/assets/images/login/fileNum.png differ diff --git a/assets/images/login/forget.png b/assets/images/login/forget.png new file mode 100644 index 00000000..57aa7ccc Binary files /dev/null and b/assets/images/login/forget.png differ diff --git a/assets/images/login/id.png b/assets/images/login/id.png new file mode 100644 index 00000000..9260cf11 Binary files /dev/null and b/assets/images/login/id.png differ diff --git a/assets/images/login/more_icon.png b/assets/images/login/more_icon.png new file mode 100644 index 00000000..b696d345 Binary files /dev/null and b/assets/images/login/more_icon.png differ diff --git a/assets/images/login/nationalID.png b/assets/images/login/nationalID.png new file mode 100644 index 00000000..5779d562 Binary files /dev/null and b/assets/images/login/nationalID.png differ diff --git a/assets/images/progress-loading-red.gif b/assets/images/progress-loading-red.gif new file mode 100644 index 00000000..517c3dab Binary files /dev/null and b/assets/images/progress-loading-red.gif differ diff --git a/assets/images/vital_blood-pressure.png b/assets/images/vital_blood-pressure.png new file mode 100644 index 00000000..44c9f2e2 Binary files /dev/null and b/assets/images/vital_blood-pressure.png differ diff --git a/assets/images/vital_blood_type.png b/assets/images/vital_blood_type.png new file mode 100644 index 00000000..fbb5296f Binary files /dev/null and b/assets/images/vital_blood_type.png differ diff --git a/assets/images/vital_body_mass.png b/assets/images/vital_body_mass.png new file mode 100644 index 00000000..08476c51 Binary files /dev/null and b/assets/images/vital_body_mass.png differ diff --git a/assets/images/vital_heart_rate.png b/assets/images/vital_heart_rate.png new file mode 100644 index 00000000..e788658b Binary files /dev/null and b/assets/images/vital_heart_rate.png differ diff --git a/assets/images/vital_height.png b/assets/images/vital_height.png new file mode 100644 index 00000000..8c324b2c Binary files /dev/null and b/assets/images/vital_height.png differ diff --git a/assets/images/vital_respiration.png b/assets/images/vital_respiration.png new file mode 100644 index 00000000..7e1b4466 Binary files /dev/null and b/assets/images/vital_respiration.png differ diff --git a/assets/images/vital_signs.png b/assets/images/vital_signs.png new file mode 100644 index 00000000..7b642d6e Binary files /dev/null and b/assets/images/vital_signs.png differ diff --git a/assets/images/vital_temperature.png b/assets/images/vital_temperature.png new file mode 100644 index 00000000..7fe657de Binary files /dev/null and b/assets/images/vital_temperature.png differ diff --git a/assets/images/vital_weight.png b/assets/images/vital_weight.png new file mode 100644 index 00000000..5247e924 Binary files /dev/null and b/assets/images/vital_weight.png differ diff --git a/lib/client/base_app_client.dart b/lib/client/base_app_client.dart index e203c142..c1438159 100644 --- a/lib/client/base_app_client.dart +++ b/lib/client/base_app_client.dart @@ -71,9 +71,14 @@ class BaseAppClient { body['SessionID'] = SESSION_ID; body['IsLoginForDoctorApp'] = IS_LOGIN_FOR_DOCTOR_APP; body['PatientOutSA'] = 0; // PATIENT_OUT_SA; - body['VidaAuthTokenID'] = await sharedPref.getString(VIDA_AUTH_TOKEN_ID); - body['VidaRefreshTokenID'] = - await sharedPref.getString(VIDA_REFRESH_TOKEN_ID); + if (body['VidaAuthTokenID'] == null) { + body['VidaAuthTokenID'] = + await sharedPref.getString(VIDA_AUTH_TOKEN_ID); + } + if (body['VidaRefreshTokenID'] == null) { + body['VidaRefreshTokenID'] = + await sharedPref.getString(VIDA_REFRESH_TOKEN_ID); + } print("URL : $url"); print("Body : ${json.encode(body)}"); diff --git a/lib/config/config.dart b/lib/config/config.dart index b07e3341..9fd3f14a 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -71,6 +71,10 @@ const CREATE_REFERRAL_PATIENT = const RESPONSE_PENDING_REFERRAL_PATIENT = 'Services/DoctorApplication.svc/REST/CreateReferral'; +const GET_PATIENT_REFERRAL = 'Services/DoctorApplication.svc/REST/GetRefferal'; + +const POST_UCAF = 'Services/DoctorApplication.svc/REST/PostUCAF'; + const GET_DOCTOR_WORKING_HOURS_TABLE = 'Services/Doctors.svc/REST/GetDoctorWorkingHoursTable'; @@ -78,9 +82,13 @@ const GET_PATIENT_LAB_RESULTS = 'Services/DoctorApplication.svc/REST/GetPatientLabResults'; const LOGIN_URL = 'Services/Sentry.svc/REST/MemberLogIN_New'; const INSERT_DEVICE_IMEI = - 'Services/Sentry.svc/REST/DoctorApplication_INSERTDeviceIMEI'; + 'Services/DoctorApplication.svc/REST/DoctorApp_InsertOrUpdateDeviceDetails'; +// 'Services/Sentry.svc/REST/DoctorApplication_INSERTDeviceIMEI'; +// const SELECT_DEVICE_IMEI = +// 'Services/Sentry.svc/REST/DoctorApplication_SELECTDeviceIMEIbyIMEI'; + const SELECT_DEVICE_IMEI = - 'Services/Sentry.svc/REST/DoctorApplication_SELECTDeviceIMEIbyIMEI'; + 'Services/DoctorApplication.svc/REST/DoctorApp_GetDeviceDetailsByIMEI'; const SEND_ACTIVATION_CODE_BY_OTP_NOTIFICATION_TYPE = 'Services/Sentry.svc/REST/DoctorApplication_SendActivationCodebyOTPNotificationType'; @@ -88,6 +96,8 @@ const SEND_ACTIVATION_CODE_BY_OTP_NOTIFICATION_TYPE = const SEND_ACTIVATION_CODE_FOR_DOCTOR_APP = 'Services/DoctorApplication.svc/REST/SendActivationCodeForDoctorApp'; +const SEND_ACTIVATION_CODE_FOR_VERIFICATION_SCREEN = + 'Services/DoctorApplication.svc/REST/SendVerificationCode'; const MEMBER_CHECK_ACTIVATION_CODE_NEW = 'Services/Sentry.svc/REST/MemberCheckActivationCode_New'; @@ -133,6 +143,9 @@ const GET_PATIENT_ARRIVAL_LIST = const GET_ALLERGIES = 'Services/DoctorApplication.svc/REST/GetAllergies'; const GET_MASTER_LOOKUP_LIST = 'Services/DoctorApplication.svc/REST/GetMasterLookUpList'; + +const POST_EPISODE = 'Services/DoctorApplication.svc/REST/PostEpisode'; + const POST_ALLERGY = 'Services/DoctorApplication.svc/REST/PostAllergies'; const POST_HISTORY = 'Services/DoctorApplication.svc/REST/PostHistory'; const POST_CHIEF_COMPLAINT = @@ -173,7 +186,8 @@ const UPDATE_PROCEDURE = 'Services/DoctorApplication.svc/REST/PatchProcedure'; const UPDATE_PRESCRIPTION = 'Services/DoctorApplication.svc/REST/PatchPrescription'; const SEARCH_DRUG = 'Services/DoctorApplication.svc/REST/GetMedicationList'; - +const DRUG_TO_DRUG = + 'Services/DoctorApplication.svc/REST/DrugToDrugInteraction'; const GET_MEDICAL_FILE = 'Services/DoctorApplication.svc/REST/GetMedicalFile'; var selectedPatientType = 1; @@ -222,6 +236,8 @@ var SERVICES_PATIANT_HEADER_AR = [ //****************** // Colors ////// by : ibrahim + +var DEVICE_TOKEN = ""; const PRIMARY_COLOR = 0xff515B5D; const TRANSACTION_NO = 0; diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 2b6b86de..426a309b 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -295,7 +295,10 @@ const Map> localizedValues = { }, 'clinicSelect': {'en': "Select Clinic", 'ar': 'اختار عيادة'}, 'doctorSelect': {'en': "Select Doctor", 'ar': 'اختار طبيب'}, - "empty-message": {"en": "Please enter message", "ar": "يرجى ادخال الموضوع"}, + "empty-message": { + "en": "Please enter this field", + "ar": "يرجى ادخال هذا الحقل" + }, 'no-sickleve-applied': { 'en': "No sick leave applied", 'ar': 'لم تطبق إجازة مرضية' @@ -536,6 +539,70 @@ const Map> localizedValues = { 'en': "There is no Chief Complaint", 'ar': "ليس هناك شكوى رئيس" }, + "more-verify": { + "en": "More Verification Options", + "ar": "المزيد من خيارات التحقق" + }, + "welcome-back": {"en": "Welcome back!", "ar": "مرحبا بعودتك!"}, + "account-info": { + "en": "Would you like to login with current username?", + "ar": "هل ترغب في تسجيل الدخول باسم المستخدم الحالي؟" + }, + "another-acc": {"en": "Use Another Account", "ar": "استخدم حسابا آخر"}, + "verify-login-with": { + "en": "Please choose one of the following options to verify", + "ar": "الرجاء اختيار احدى الخيارات التالية للتحقق من البيانات" + }, + "register-user": {"en": "Register", "ar": "تسجيل"}, + "verify-with-fingerprint": {"en": "Fingerprint", "ar": "بصمة"}, + "verify-with-faceid": {"en": "Face ID", "ar": "معرف الوجه"}, + "verify-with-sms": {"en": "SMS", "ar": "الرسائل القصيرة"}, + "verify-with-whatsapp": {"en": "Whatsapp", "ar": " الواتس اب"}, + "last-login": {"en": "LAST LOGIN AT:", "ar": "آخر تسجيل دخول"}, + "last-login-with": {"en": "VERIFICATION TYPE:", "ar": "نوع التحقق:"}, + "verify-fingerprint": { + "en": + "To activate the fingerprint login service, please verify data by using one of the following options.", + "ar": + "لتفعيل خدمة الدخول بالبصمة، يرجى اختيار احدى القنوات التالية للتحقق من البيانات" + }, + "verification_message": { + "en": "Please enter the Verification Code sent to", + "ar": "الرجاء ادخال رمز التحقق الذي تم إرساله إلى" + }, + "validation_message": { + "en": "The verification code expires in", + "ar": "تنتهي صلاحية رمز التحقق خلال" + }, + 'addAssessment': {'en': "Add ASSESSMENT", 'ar': "أضف التقييم"}, + 'assessment': {'en': "ASSESSMENT", 'ar': " التقييم"}, + 'physicalSystemExamination': { + 'en': "Physical/System Examination", + 'ar': " الفحص البدني / النظام" + }, + 'searchExamination': {'en': "Search Examination", 'ar': "فحص البحث"}, + 'addExamination': {'en': "Add Examination", 'ar': "اضافه"}, + 'doc': {'en': "Doc :", 'ar': " د: "}, + 'patientNoDetailErrMsg': { + 'en': "There is no detail for this patient", + 'ar': "لا توجد تفاصيل لهذا المريض" + }, + "systolic-lng": { + "en": "Systolic", + "ar": "الإنقباض" + }, + "diastolic-lng": { + "en": "Diastolic", + "ar": "الإنبساط" + }, + "mass": {"en": "Mass", "ar": "كتلة"}, + "temp-c": {"en": "°C", "ar": "°س"}, + "bpm": {"en": "bpm", "ar": "نبضة"}, + "respiration-signs": {"en": "Respiration", "ar": "تنفس"}, + "sys-dias": {"en": "SBP/DBP", "ar": "إنقباض/إنبساط"}, + "body": {"en": "Body \n Mass", "ar": "كتلة\nالجسم"}, + 'respirationRate': {'en': 'Respiration Rate', 'ar': 'معدل التنفس'}, + 'heart': {'en': 'Heart', 'ar': 'قلب'}, 'addAssessment': {'en': "Add ASSESSMENT", 'ar': "أضف التقييم"}, 'assessment': {'en': "ASSESSMENT", 'ar': " التقييم"}, 'physicalSystemExamination': { diff --git a/lib/config/shared_pref_kay.dart b/lib/config/shared_pref_kay.dart index e483c7d1..1520207f 100644 --- a/lib/config/shared_pref_kay.dart +++ b/lib/config/shared_pref_kay.dart @@ -10,3 +10,5 @@ final DOCTOR_PROFILE = 'doctorProfile'; final LIVE_CARE_PATIENT = 'livecare-patient-profile'; final LOGGED_IN_USER = 'loggedUser'; final DASHBOARD_DATA = 'dashboard-data'; +final OTP_TYPE = 'otp-type'; +final LAST_LOGIN_USER = 'last-login-user'; diff --git a/lib/core/model/imei_details.dart b/lib/core/model/imei_details.dart new file mode 100644 index 00000000..614ce67a --- /dev/null +++ b/lib/core/model/imei_details.dart @@ -0,0 +1,124 @@ +class GetIMEIDetailsModel { + int iD; + String iMEI; + int logInTypeID; + bool outSA; + String mobile; + Null identificationNo; + int doctorID; + String doctorName; + String doctorNameN; + int clinicID; + String clinicDescription; + Null clinicDescriptionN; + int projectID; + String projectName; + String genderDescription; + Null genderDescriptionN; + String titleDescription; + Null titleDescriptionN; + Null zipCode; + String createdOn; + Null createdBy; + String editedOn; + int editedBy; + bool biometricEnabled; + Null preferredLanguage; + bool isActive; + String vidaAuthTokenID; + String vidaRefreshTokenID; + + GetIMEIDetailsModel( + {this.iD, + this.iMEI, + this.logInTypeID, + this.outSA, + this.mobile, + this.identificationNo, + this.doctorID, + this.doctorName, + this.doctorNameN, + this.clinicID, + this.clinicDescription, + this.clinicDescriptionN, + this.projectID, + this.projectName, + this.genderDescription, + this.genderDescriptionN, + this.titleDescription, + this.titleDescriptionN, + this.zipCode, + this.createdOn, + this.createdBy, + this.editedOn, + this.editedBy, + this.biometricEnabled, + this.preferredLanguage, + this.isActive, + this.vidaAuthTokenID, + this.vidaRefreshTokenID}); + + GetIMEIDetailsModel.fromJson(Map json) { + iD = json['ID']; + iMEI = json['IMEI']; + logInTypeID = json['LogInTypeID']; + outSA = json['OutSA']; + mobile = json['Mobile']; + identificationNo = json['IdentificationNo']; + doctorID = json['DoctorID']; + doctorName = json['DoctorName']; + doctorNameN = json['DoctorNameN']; + clinicID = json['ClinicID']; + clinicDescription = json['ClinicDescription']; + clinicDescriptionN = json['ClinicDescriptionN']; + projectID = json['ProjectID']; + projectName = json['ProjectName']; + genderDescription = json['Gender_Description']; + genderDescriptionN = json['Gender_DescriptionN']; + titleDescription = json['Title_Description']; + titleDescriptionN = json['Title_DescriptionN']; + zipCode = json['ZipCode']; + createdOn = json['CreatedOn']; + createdBy = json['CreatedBy']; + editedOn = json['EditedOn']; + editedBy = json['EditedBy']; + biometricEnabled = json['BiometricEnabled']; + preferredLanguage = json['PreferredLanguage']; + isActive = json['IsActive']; + vidaAuthTokenID = json['VidaAuthTokenID']; + vidaRefreshTokenID = json['VidaRefreshTokenID']; + } + + Map toJson() { + final Map data = new Map(); + data['ID'] = this.iD; + data['IMEI'] = this.iMEI; + data['LogInTypeID'] = this.logInTypeID; + data['OutSA'] = this.outSA; + data['Mobile'] = this.mobile; + data['IdentificationNo'] = this.identificationNo; + data['DoctorID'] = this.doctorID; + data['DoctorName'] = this.doctorName; + data['DoctorNameN'] = this.doctorNameN; + data['ClinicID'] = this.clinicID; + data['ClinicDescription'] = this.clinicDescription; + data['ClinicDescriptionN'] = this.clinicDescriptionN; + data['ProjectID'] = this.projectID; + data['ProjectName'] = this.projectName; + data['Gender_Description'] = this.genderDescription; + data['Gender_DescriptionN'] = this.genderDescriptionN; + data['Title_Description'] = this.titleDescription; + data['Title_DescriptionN'] = this.titleDescriptionN; + data['ZipCode'] = this.zipCode; + data['CreatedOn'] = this.createdOn; + data['CreatedBy'] = this.createdBy; + data['EditedOn'] = this.editedOn; + data['EditedBy'] = this.editedBy; + data['BiometricEnabled'] = this.biometricEnabled; + data['PreferredLanguage'] = this.preferredLanguage; + data['IsActive'] = this.isActive; + data['VidaAuthTokenID'] = this.vidaAuthTokenID; + data['VidaRefreshTokenID'] = this.vidaRefreshTokenID; + return data; + } +} diff --git a/lib/core/model/insert_imei_model.dart b/lib/core/model/insert_imei_model.dart new file mode 100644 index 00000000..40668dba --- /dev/null +++ b/lib/core/model/insert_imei_model.dart @@ -0,0 +1,140 @@ +class InsertIMEIDetailsModel { + String iMEI; + int logInTypeID; + Null outSA; + Null mobile; + Null identificationNo; + int doctorID; + String doctorName; + String doctorNameN; + int clinicID; + String clinicDescription; + Null clinicDescriptionN; + String projectName; + String genderDescription; + Null genderDescriptionN; + String titleDescription; + Null titleDescriptionN; + bool bioMetricEnabled; + Null preferredLanguage; + bool isActive; + int editedBy; + int projectID; + String tokenID; + int languageID; + String stamp; + String iPAdress; + double versionID; + int channel; + String sessionID; + bool isLoginForDoctorApp; + int patientOutSA; + String vidaAuthTokenID; + String vidaRefreshTokenID; + + InsertIMEIDetailsModel( + {this.iMEI, + this.logInTypeID, + this.outSA, + this.mobile, + this.identificationNo, + this.doctorID, + this.doctorName, + this.doctorNameN, + this.clinicID, + this.clinicDescription, + this.clinicDescriptionN, + this.projectName, + this.genderDescription, + this.genderDescriptionN, + this.titleDescription, + this.titleDescriptionN, + this.bioMetricEnabled, + this.preferredLanguage, + this.isActive, + this.editedBy, + this.projectID, + this.tokenID, + this.languageID, + this.stamp, + this.iPAdress, + this.versionID, + this.channel, + this.sessionID, + this.isLoginForDoctorApp, + this.patientOutSA, + this.vidaAuthTokenID, + this.vidaRefreshTokenID}); + + InsertIMEIDetailsModel.fromJson(Map json) { + iMEI = json['IMEI']; + logInTypeID = json['LogInTypeID']; + outSA = json['OutSA']; + mobile = json['Mobile']; + identificationNo = json['IdentificationNo']; + doctorID = json['DoctorID']; + doctorName = json['DoctorName']; + doctorNameN = json['DoctorNameN']; + clinicID = json['ClinicID']; + clinicDescription = json['ClinicDescription']; + clinicDescriptionN = json['ClinicDescriptionN']; + projectName = json['ProjectName']; + genderDescription = json['GenderDescription']; + genderDescriptionN = json['GenderDescriptionN']; + titleDescription = json['TitleDescription']; + titleDescriptionN = json['Title_DescriptionN']; + bioMetricEnabled = json['BioMetricEnabled']; + preferredLanguage = json['PreferredLanguage']; + isActive = json['IsActive']; + editedBy = json['EditedBy']; + projectID = json['ProjectID']; + tokenID = json['TokenID']; + languageID = json['LanguageID']; + stamp = json['stamp']; + iPAdress = json['IPAdress']; + versionID = json['VersionID']; + channel = json['Channel']; + sessionID = json['SessionID']; + isLoginForDoctorApp = json['IsLoginForDoctorApp']; + patientOutSA = json['PatientOutSA']; + vidaAuthTokenID = json['VidaAuthTokenID']; + vidaRefreshTokenID = json['VidaRefreshTokenID']; + } + + Map toJson() { + final Map data = new Map(); + data['IMEI'] = this.iMEI; + data['LogInTypeID'] = this.logInTypeID; + data['OutSA'] = this.outSA; + data['Mobile'] = this.mobile; + data['IdentificationNo'] = this.identificationNo; + data['DoctorID'] = this.doctorID; + data['DoctorName'] = this.doctorName; + data['DoctorNameN'] = this.doctorNameN; + data['ClinicID'] = this.clinicID; + data['ClinicDescription'] = this.clinicDescription; + data['ClinicDescriptionN'] = this.clinicDescriptionN; + data['ProjectName'] = this.projectName; + data['GenderDescription'] = this.genderDescription; + data['GenderDescriptionN'] = this.genderDescriptionN; + data['TitleDescription'] = this.titleDescription; + data['Title_DescriptionN'] = this.titleDescriptionN; + data['BioMetricEnabled'] = this.bioMetricEnabled; + data['PreferredLanguage'] = this.preferredLanguage; + data['IsActive'] = this.isActive; + data['EditedBy'] = this.editedBy; + data['ProjectID'] = this.projectID; + data['TokenID'] = this.tokenID; + data['LanguageID'] = this.languageID; + data['stamp'] = this.stamp; + data['IPAdress'] = this.iPAdress; + data['VersionID'] = this.versionID; + data['Channel'] = this.channel; + data['SessionID'] = this.sessionID; + data['IsLoginForDoctorApp'] = this.isLoginForDoctorApp; + data['PatientOutSA'] = this.patientOutSA; + data['VidaAuthTokenID'] = this.vidaAuthTokenID; + data['VidaRefreshTokenID'] = this.vidaRefreshTokenID; + return data; + } +} diff --git a/lib/core/service/SOAP_service.dart b/lib/core/service/SOAP_service.dart index d1fff03b..e3ab61b2 100644 --- a/lib/core/service/SOAP_service.dart +++ b/lib/core/service/SOAP_service.dart @@ -11,6 +11,7 @@ import 'package:doctor_app_flutter/models/SOAP/GetHistoryReqModel.dart'; import 'package:doctor_app_flutter/models/SOAP/GetHistoryResModel.dart'; import 'package:doctor_app_flutter/models/SOAP/GetPhysicalExamListResModel.dart'; import 'package:doctor_app_flutter/models/SOAP/GetPhysicalExamReqModel.dart'; +import 'package:doctor_app_flutter/models/SOAP/PostEpisodeReqModel.dart'; import 'package:doctor_app_flutter/models/SOAP/get_Allergies_request_model.dart'; import 'package:doctor_app_flutter/models/SOAP/master_key_model.dart'; import 'package:doctor_app_flutter/models/SOAP/post_allergy_request_model.dart'; @@ -31,6 +32,7 @@ class SOAPService extends LookupService { List patientProgressNoteList = []; List patientAssessmentList = []; + int episodeID; Future getAllergies(GetAllergiesRequestModel getAllergiesRequestModel) async { await baseAppClient.post( GET_ALLERGIES, @@ -48,6 +50,20 @@ class SOAPService extends LookupService { ); } + Future postEpisode(PostEpisodeReqModel postEpisodeReqModel) async { + hasError = false; + + await baseAppClient.post(POST_EPISODE, + onSuccess: (dynamic response, int statusCode) { + + print("Success"); + episodeID = response['EpisodeID']; + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: postEpisodeReqModel.toJson()); + } + Future postAllergy(PostAllergyRequestModel postAllergyRequestModel) async { hasError = false; diff --git a/lib/core/service/auth_service.dart b/lib/core/service/auth_service.dart new file mode 100644 index 00000000..e116ccdd --- /dev/null +++ b/lib/core/service/auth_service.dart @@ -0,0 +1,29 @@ +import 'package:doctor_app_flutter/config/config.dart'; +import 'package:doctor_app_flutter/core/model/imei_details.dart'; +import 'package:doctor_app_flutter/core/service/base/base_service.dart'; +import 'package:doctor_app_flutter/models/dashboard/dashboard_model.dart'; + +class AuthService extends BaseService { + List _imeiDetails = []; + List get dashboardItemsList => _imeiDetails; + + Future selectDeviceImei(imei) async { + try { + // dynamic localRes; + await baseAppClient.post(SELECT_DEVICE_IMEI, + onSuccess: (dynamic response, int statusCode) { + _imeiDetails = []; + response['List_DoctorDeviceDetails'].forEach((v) { + _imeiDetails.add(GetIMEIDetailsModel.fromJson(v)); + }); + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: {"IMEI": imei, "TokenID": "@dm!n"}); + //return Future.value(localRes); + } catch (error) { + hasError = true; + super.error = error; + } + } +} diff --git a/lib/core/service/base/base_service.dart b/lib/core/service/base/base_service.dart index 32edf34f..6f4c5d1e 100644 --- a/lib/core/service/base/base_service.dart +++ b/lib/core/service/base/base_service.dart @@ -1,4 +1,5 @@ import 'package:doctor_app_flutter/client/base_app_client.dart'; +import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart'; import 'package:doctor_app_flutter/util/dr_app_shared_pref.dart'; import 'package:doctor_app_flutter/config/config.dart'; import 'package:doctor_app_flutter/config/shared_pref_kay.dart'; @@ -12,7 +13,7 @@ class BaseService { DrAppSharedPreferances sharedPref = new DrAppSharedPreferances(); DoctorProfileModel doctorProfile; - List patientArrivalList = []; + List patientArrivalList = []; //TODO add the user login model when we need it Future getDoctorProfile() async { @@ -50,7 +51,7 @@ class BaseService { patientArrivalList.clear(); response['patientArrivalList']['entityList'].forEach((v) { - PatientArrivalEntity item = PatientArrivalEntity.fromJson(v); + PatiantInformtion item = PatiantInformtion.fromJson(v); patientArrivalList.add(item); }); }, diff --git a/lib/core/service/medicine_service.dart b/lib/core/service/medicine_service.dart index df23172f..f205dab1 100644 --- a/lib/core/service/medicine_service.dart +++ b/lib/core/service/medicine_service.dart @@ -14,7 +14,6 @@ class MedicineService extends BaseService { PharmaciesItemsRequestModel(); PharmaciesListRequestModel _listRequestModel = PharmaciesListRequestModel(); - Future getMedicineItem(String itemName) async { _itemsRequestModel.pHRItemName = itemName; await baseAppClient.post( diff --git a/lib/core/service/patient-doctor-referral-service.dart b/lib/core/service/patient-doctor-referral-service.dart index 7eb8001b..2f18540a 100644 --- a/lib/core/service/patient-doctor-referral-service.dart +++ b/lib/core/service/patient-doctor-referral-service.dart @@ -18,6 +18,7 @@ class PatientReferralService extends LookupService { List doctorsList = []; List listMyReferredPatientModel = []; List pendingReferralList = []; + List patientReferralList = []; String setupID = "0"; Future getProjectsList() async { @@ -163,6 +164,33 @@ class PatientReferralService extends LookupService { ); } + Future getPatientReferral(PatiantInformtion patient) async { + hasError = false; + Map body = Map(); + body['PatientMRN'] = patient.patientMRN; + body['AppointmentNo'] = patient.appointmentNo; + + await baseAppClient.post( + GET_PATIENT_REFERRAL, + onSuccess: (dynamic response, int statusCode) { + patientReferralList.clear(); + + response['ReferralList']['entityList'].forEach((v) { + PendingReferral item = PendingReferral.fromJson(v); + item.isReferralDoctorSameBranch = + item.targetProjectId == item.sourceProjectId; + patientReferralList.add(item); + }); + }, + onFailure: (String error, int statusCode) { + patientReferralList.clear(); + hasError = true; + super.error = error; + }, + body: body, + ); + } + Future responseReferral(PendingReferral pendingReferral, bool isAccepted) async { hasError = false; DoctorProfileModel doctorProfile = await getDoctorProfile(); @@ -221,6 +249,7 @@ class PatientReferralService extends LookupService { CREATE_REFERRAL_PATIENT, onSuccess: (dynamic response, int statusCode) { print(response.toString()); + print("create referral status code = ${statusCode}"); }, onFailure: (String error, int statusCode) { hasError = true; diff --git a/lib/core/service/patient-vital-signs-service.dart b/lib/core/service/patient-vital-signs-service.dart index 8d0cfc31..ed6869f8 100644 --- a/lib/core/service/patient-vital-signs-service.dart +++ b/lib/core/service/patient-vital-signs-service.dart @@ -3,13 +3,12 @@ import 'package:doctor_app_flutter/core/service/base/base_service.dart'; import 'package:doctor_app_flutter/models/patient/PatientArrivalEntity.dart'; import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart'; import 'package:doctor_app_flutter/models/patient/vital_sign/patient-vital-sign-data.dart'; +import 'package:doctor_app_flutter/models/patient/vital_sign/patient-vital-sign-history.dart'; import 'package:doctor_app_flutter/models/patient/vital_sign/vital_sign_res_model.dart'; -class VitalSignsService extends BaseService{ - - List patientVitalSignList = []; - List patientVitalSignOrderdSubList = []; +class VitalSignsService extends BaseService { VitalSignData patientVitalSigns; + List patientVitalSignsHistory = []; Future getPatientVitalSign(PatiantInformtion patient) async { patientVitalSigns = null; @@ -18,13 +17,14 @@ class VitalSignsService extends BaseService{ body['PatientMRN'] = patient.patientMRN; body['AppointmentNo'] = patient.appointmentNo; body['EpisodeID'] = patient.episodeNo; - await baseAppClient.post( GET_PATIENT_VITAL_SIGN_DATA, onSuccess: (dynamic response, int statusCode) { - if(response['VitalSignsList'] != null){ - if(response['VitalSignsList']['entityList'] != null && (response['VitalSignsList']['entityList'] as List).length > 0){ - patientVitalSigns = VitalSignData.fromJson(response['VitalSignsList']['entityList'][0]); + if (response['VitalSignsList'] != null) { + if (response['VitalSignsList']['entityList'] != null && + (response['VitalSignsList']['entityList'] as List).length > 0) { + patientVitalSigns = VitalSignData.fromJson( + response['VitalSignsList']['entityList'][0]); } } }, @@ -35,4 +35,37 @@ class VitalSignsService extends BaseService{ body: body, ); } -} \ No newline at end of file + + Future getPatientVitalSignsHistory( + PatiantInformtion patient, String fromDate, String toDate) async { + patientVitalSigns = null; + hasError = false; + Map body = Map(); + body['PatientMRN'] = patient.patientMRN; + body['AppointmentNo'] = patient.appointmentNo; + body['EpisodeID'] = patient.episodeNo; + body['PatientTypeID'] = 1; + body['PatientType'] = 1; + body['DeviceTypeID'] = 1; + body['isDentalAllowedBackend'] = false; + body['From'] = fromDate; + body['To'] = toDate; + + await baseAppClient.post( + GET_PATIENT_VITAL_SIGN_DATA, + onSuccess: (dynamic response, int statusCode) { + patientVitalSignsHistory.clear(); + if (response['VitalSignsHistory'] != null) { + response['VitalSignsHistory'].forEach((v) { + patientVitalSignsHistory.add(new VitalSignHistory.fromJson(v)); + }); + } + }, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error.toString(); + }, + body: body, + ); + } +} diff --git a/lib/core/service/prescription_service.dart b/lib/core/service/prescription_service.dart index 41adcbc0..90b12041 100644 --- a/lib/core/service/prescription_service.dart +++ b/lib/core/service/prescription_service.dart @@ -5,6 +5,9 @@ import 'package:doctor_app_flutter/core/model/post_prescrition_req_model.dart'; import 'package:doctor_app_flutter/core/model/search_drug_model.dart'; import 'package:doctor_app_flutter/core/model/search_drug_request_model.dart'; import 'package:doctor_app_flutter/core/service/base/base_service.dart'; +import 'package:doctor_app_flutter/models/SOAP/GetAllergiesResModel.dart'; +import 'package:doctor_app_flutter/models/SOAP/master_key_model.dart'; +import 'package:doctor_app_flutter/models/patient/vital_sign/patient-vital-sign-data.dart'; class PrescriptionService extends BaseService { List _prescriptionList = List(); @@ -13,12 +16,16 @@ class PrescriptionService extends BaseService { List get drugsList => _drugsList; List doctorsList = []; List specialityList = []; + List drugToDrug = []; PrescriptionReqModel _prescriptionReqModel = PrescriptionReqModel(); SearchDrugRequestModel _drugRequestModel = SearchDrugRequestModel( + //search: ["Acetaminophen"], + // vidaAuthTokenID: + // "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMDAyIiwianRpIjoiY2QwOWU3MTEtZDEwYy00NjZhLWEwNDctMjc4MDBmNmRkMTYxIiwiZW1haWwiOiIiLCJpZCI6IjEwMDIiLCJOYW1lIjoiVEVNUCAtIERPQ1RPUiIsIkVtcGxveWVlSWQiOiI0NzA5IiwiRmFjaWxpdHlHcm91cElkIjoiMDEwMjY2IiwiRmFjaWxpdHlJZCI6IjE1IiwiUGhhcmFtY3lGYWNpbGl0eUlkIjoiNTUiLCJJU19QSEFSTUFDWV9DT05ORUNURUQiOiJUcnVlIiwiRG9jdG9ySWQiOiI0NzA5IiwiU0VTU0lPTklEIjoiMjE1OTYyMDMiLCJDbGluaWNJZCI6IjEiLCJyb2xlIjpbIkhFQUQgTlVSU0VTIiwiRE9DVE9SUyIsIkhFQUQgRE9DVE9SUyIsIkFETUlOSVNUUkFUT1JTIiwiUkVDRVBUSU9OSVNUIiwiRVIgTlVSU0UiLCJJVkYgUkVDRVBUSU9OSVNUIiwiRVIgUkVDRVBUSU9OSVNUIiwiUEhBUk1BQ1kgQUNDT1VOVCBTVEFGRiIsIlBIQVJNQUNZIE5VUlNFIiwiSU5QQVRJRU5UIFBIQVJNQUNJU1QiLCJBRE1JU1NJT04gU1RBRkYiLCJBUFBST1ZBTCBTVEFGRiIsIklWRiBET0NUT1IiLCJJVkYgTlVSU0UiLCJJVkYgQ09PUkRJTkFUT1IiLCJJVkYgTEFCIFNUQUZGIiwiQ09OU0VOVCAiLCJNRURJQ0FMIFJFUE9SVCAtIFNJQ0sgTEVBVkUgTUFOQUdFUiJdLCJuYmYiOjE2MDkyNjQ2MTQsImV4cCI6MTYxMDEyODYxNCwiaWF0IjoxNjA5MjY0NjE0fQ.xCJ0jGtSFf36G8uZpdmHVoLfXDyP6e9mBpuOPSlzuio", search: ["Amoxicillin"], - vidaAuthTokenID: - "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMDAyIiwianRpIjoiY2QwOWU3MTEtZDEwYy00NjZhLWEwNDctMjc4MDBmNmRkMTYxIiwiZW1haWwiOiIiLCJpZCI6IjEwMDIiLCJOYW1lIjoiVEVNUCAtIERPQ1RPUiIsIkVtcGxveWVlSWQiOiI0NzA5IiwiRmFjaWxpdHlHcm91cElkIjoiMDEwMjY2IiwiRmFjaWxpdHlJZCI6IjE1IiwiUGhhcmFtY3lGYWNpbGl0eUlkIjoiNTUiLCJJU19QSEFSTUFDWV9DT05ORUNURUQiOiJUcnVlIiwiRG9jdG9ySWQiOiI0NzA5IiwiU0VTU0lPTklEIjoiMjE1OTYyMDMiLCJDbGluaWNJZCI6IjEiLCJyb2xlIjpbIkhFQUQgTlVSU0VTIiwiRE9DVE9SUyIsIkhFQUQgRE9DVE9SUyIsIkFETUlOSVNUUkFUT1JTIiwiUkVDRVBUSU9OSVNUIiwiRVIgTlVSU0UiLCJJVkYgUkVDRVBUSU9OSVNUIiwiRVIgUkVDRVBUSU9OSVNUIiwiUEhBUk1BQ1kgQUNDT1VOVCBTVEFGRiIsIlBIQVJNQUNZIE5VUlNFIiwiSU5QQVRJRU5UIFBIQVJNQUNJU1QiLCJBRE1JU1NJT04gU1RBRkYiLCJBUFBST1ZBTCBTVEFGRiIsIklWRiBET0NUT1IiLCJJVkYgTlVSU0UiLCJJVkYgQ09PUkRJTkFUT1IiLCJJVkYgTEFCIFNUQUZGIiwiQ09OU0VOVCAiLCJNRURJQ0FMIFJFUE9SVCAtIFNJQ0sgTEVBVkUgTUFOQUdFUiJdLCJuYmYiOjE2MDkyNjQ2MTQsImV4cCI6MTYxMDEyODYxNCwiaWF0IjoxNjA5MjY0NjE0fQ.xCJ0jGtSFf36G8uZpdmHVoLfXDyP6e9mBpuOPSlzuio", + //vidaAuthTokenID: + // "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMDAyIiwianRpIjoiY2QwOWU3MTEtZDEwYy00NjZhLWEwNDctMjc4MDBmNmRkMTYxIiwiZW1haWwiOiIiLCJpZCI6IjEwMDIiLCJOYW1lIjoiVEVNUCAtIERPQ1RPUiIsIkVtcGxveWVlSWQiOiI0NzA5IiwiRmFjaWxpdHlHcm91cElkIjoiMDEwMjY2IiwiRmFjaWxpdHlJZCI6IjE1IiwiUGhhcmFtY3lGYWNpbGl0eUlkIjoiNTUiLCJJU19QSEFSTUFDWV9DT05ORUNURUQiOiJUcnVlIiwiRG9jdG9ySWQiOiI0NzA5IiwiU0VTU0lPTklEIjoiMjE1OTYyMDMiLCJDbGluaWNJZCI6IjEiLCJyb2xlIjpbIkhFQUQgTlVSU0VTIiwiRE9DVE9SUyIsIkhFQUQgRE9DVE9SUyIsIkFETUlOSVNUUkFUT1JTIiwiUkVDRVBUSU9OSVNUIiwiRVIgTlVSU0UiLCJJVkYgUkVDRVBUSU9OSVNUIiwiRVIgUkVDRVBUSU9OSVNUIiwiUEhBUk1BQ1kgQUNDT1VOVCBTVEFGRiIsIlBIQVJNQUNZIE5VUlNFIiwiSU5QQVRJRU5UIFBIQVJNQUNJU1QiLCJBRE1JU1NJT04gU1RBRkYiLCJBUFBST1ZBTCBTVEFGRiIsIklWRiBET0NUT1IiLCJJVkYgTlVSU0UiLCJJVkYgQ09PUkRJTkFUT1IiLCJJVkYgTEFCIFNUQUZGIiwiQ09OU0VOVCAiLCJNRURJQ0FMIFJFUE9SVCAtIFNJQ0sgTEVBVkUgTUFOQUdFUiJdLCJuYmYiOjE2MDkyNjQ2MTQsImV4cCI6MTYxMDEyODYxNCwiaWF0IjoxNjA5MjY0NjE0fQ.xCJ0jGtSFf36G8uZpdmHVoLfXDyP6e9mBpuOPSlzuio", ); PostPrescriptionReqModel _postPrescriptionReqModel = @@ -84,4 +91,18 @@ class PrescriptionService extends BaseService { body: updatePrescriptionReqModel.toJson(), ); } + + Future getDrugToDrug( + VitalSignData vital, List allergy) async { + hasError = false; + var request = {}; + await baseAppClient.post(DRUG_TO_DRUG, + onSuccess: (dynamic response, int statusCode) { + drugToDrug = []; + //drugToDrug = //response['MedicationList']['entityList']; + }, onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: _drugRequestModel.toJson()); + } } diff --git a/lib/core/viewModel/SOAP_view_model.dart b/lib/core/viewModel/SOAP_view_model.dart index fff7a239..e3daf6e9 100644 --- a/lib/core/viewModel/SOAP_view_model.dart +++ b/lib/core/viewModel/SOAP_view_model.dart @@ -13,6 +13,7 @@ import 'package:doctor_app_flutter/models/SOAP/GetHistoryReqModel.dart'; import 'package:doctor_app_flutter/models/SOAP/GetHistoryResModel.dart'; import 'package:doctor_app_flutter/models/SOAP/GetPhysicalExamListResModel.dart'; import 'package:doctor_app_flutter/models/SOAP/GetPhysicalExamReqModel.dart'; +import 'package:doctor_app_flutter/models/SOAP/PostEpisodeReqModel.dart'; import 'package:doctor_app_flutter/models/SOAP/get_Allergies_request_model.dart'; import 'package:doctor_app_flutter/models/SOAP/master_key_model.dart'; import 'package:doctor_app_flutter/models/SOAP/post_allergy_request_model.dart'; @@ -78,6 +79,8 @@ class SOAPViewModel extends BaseViewModel { List get patientAssessmentList => _SOAPService.patientAssessmentList; + int get episodeID => + _SOAPService.episodeID; Future getAllergies(GetAllergiesRequestModel getAllergiesRequestModel) async { setState(ViewState.Busy); @@ -99,6 +102,17 @@ class SOAPViewModel extends BaseViewModel { setState(ViewState.Idle); } + + Future postEpisode(PostEpisodeReqModel postEpisodeReqModel) async { + setState(ViewState.BusyLocal); + await _SOAPService.postEpisode(postEpisodeReqModel); + if (_SOAPService.hasError) { + error = _SOAPService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } + Future postAllergy(PostAllergyRequestModel postAllergyRequestModel) async { setState(ViewState.BusyLocal); await _SOAPService.postAllergy(postAllergyRequestModel); @@ -222,6 +236,7 @@ class SOAPViewModel extends BaseViewModel { Future getPatientAllergy(GeneralGetReqForSOAP generalGetReqForSOAP) async { + setState(ViewState.Busy); await _SOAPService.getPatientAllergy(generalGetReqForSOAP); if (_SOAPService.hasError) { @@ -231,6 +246,14 @@ class SOAPViewModel extends BaseViewModel { setState(ViewState.Idle); } + String getAllergicNames(){ + String allergiesString=''; + patientAllergiesList.forEach((element) { + allergiesString += element.allergyDiseaseName+' , '; + }); + return allergiesString; + } + Future getPatientHistories(GetHistoryReqModel getHistoryReqModel, {bool isFirst = false}) async { setState(ViewState.Busy); await _SOAPService.getPatientHistories(getHistoryReqModel, isFirst: isFirst); diff --git a/lib/core/viewModel/auth_view_model.dart b/lib/core/viewModel/auth_view_model.dart index 47ffe730..960462cd 100644 --- a/lib/core/viewModel/auth_view_model.dart +++ b/lib/core/viewModel/auth_view_model.dart @@ -1,6 +1,13 @@ import 'package:doctor_app_flutter/client/base_app_client.dart'; +import 'package:doctor_app_flutter/core/enum/viewstate.dart'; +import 'package:doctor_app_flutter/core/model/imei_details.dart'; +import 'package:doctor_app_flutter/core/model/insert_imei_model.dart'; +import 'package:doctor_app_flutter/core/service/auth_service.dart'; +import 'package:doctor_app_flutter/core/viewModel/base_view_model.dart'; +import 'package:doctor_app_flutter/locator.dart'; import 'package:doctor_app_flutter/models/auth/activation_Code_req_model.dart'; import 'package:doctor_app_flutter/models/auth/check_activation_code_request_model.dart'; +import 'package:doctor_app_flutter/models/auth/send_activation_code_model2.dart'; import 'package:doctor_app_flutter/models/doctor/clinic_model.dart'; import 'package:doctor_app_flutter/config/shared_pref_kay.dart'; import 'package:doctor_app_flutter/models/doctor/doctor_profile_model.dart'; @@ -12,8 +19,9 @@ import '../../models/doctor/user_model.dart'; DrAppSharedPreferances sharedPref = new DrAppSharedPreferances(); enum APP_STATUS { LOADING, UNAUTHENTICATED, AUTHENTICATED } -class AuthViewModel with ChangeNotifier { +class AuthViewModel extends BaseViewModel { List doctorsClinicList = []; + String selectedClinicName; bool isLogin = false; bool isLoading = true; @@ -71,35 +79,31 @@ class AuthViewModel with ChangeNotifier { } } - Future insertDeviceImei(imei) async { + Future insertDeviceImei(request) async { + var loggedIn = await sharedPref.getObj(LOGGED_IN_USER); + + request['IMEI'] = DEVICE_TOKEN; + request['LogInTypeID'] = await sharedPref.getInt(OTP_TYPE); + request['BioMetricEnabled'] = true; + request['MobileNo'] = loggedIn['MobileNumber']; + InsertIMEIDetailsModel nRequest = InsertIMEIDetailsModel.fromJson(request); + nRequest.genderDescription = request['Gender_Description']; + nRequest.genderDescriptionN = request['Gender_DescriptionN']; + nRequest.genderDescriptionN = request['Gender_DescriptionN']; + nRequest.titleDescription = request['Title_Description']; + nRequest.titleDescriptionN = request['Title_DescriptionN']; + nRequest.projectID = await sharedPref.getInt(PROJECT_ID); + nRequest.vidaAuthTokenID = await sharedPref.getString(VIDA_AUTH_TOKEN_ID); + nRequest.vidaRefreshTokenID = + await sharedPref.getString(VIDA_REFRESH_TOKEN_ID); try { - dynamic localRes; - + var localRes; await baseAppClient.post(INSERT_DEVICE_IMEI, onSuccess: (dynamic response, int statusCode) { localRes = response; - }, onFailure: (String error, int statusCode) { - throw error; - }, body: imei); - return Future.value(localRes); - } catch (error) { - print(error); - throw error; - } - } - - Future selectDeviceImei(imei) async { - try { - dynamic localRes; - await baseAppClient.post(SELECT_DEVICE_IMEI, - onSuccess: (dynamic response, int statusCode) { - localRes = response; - }, onFailure: (String error, int statusCode) { - throw error; - }, body: imei); + }, onFailure: (String error, int statusCode) {}, body: nRequest.toJson()); return Future.value(localRes); } catch (error) { - print(error); throw error; } } @@ -120,7 +124,8 @@ class AuthViewModel with ChangeNotifier { } } - Future sendActivationCodeForDoctorApp(ActivationCodeModel activationCodeModel) async { + Future sendActivationCodeForDoctorApp( + ActivationCodeModel activationCodeModel) async { try { var localRes; await baseAppClient.post(SEND_ACTIVATION_CODE_FOR_DOCTOR_APP, @@ -158,22 +163,22 @@ class AuthViewModel with ChangeNotifier { } } - - Future checkActivationCodeForDoctorApp(CheckActivationCodeRequestModel checkActivationCodeRequestModel) async { + Future checkActivationCodeForDoctorApp( + CheckActivationCodeRequestModel checkActivationCodeRequestModel) async { try { dynamic localRes; await baseAppClient.post(CHECK_ACTIVATION_CODE_FOR_DOCTOR_APP, onSuccess: (dynamic response, int statusCode) { - localRes = response; - selectedClinicName = - ClinicModel.fromJson(response['List_DoctorsClinic'][0]).clinicName; - - response['List_DoctorsClinic'].forEach((v) { - doctorsClinicList.add(new ClinicModel.fromJson(v)); - }); - }, onFailure: (String error, int statusCode) { - throw error; - }, body: checkActivationCodeRequestModel.toJson()); + localRes = response; + selectedClinicName = + ClinicModel.fromJson(response['List_DoctorsClinic'][0]).clinicName; + + response['List_DoctorsClinic'].forEach((v) { + doctorsClinicList.add(new ClinicModel.fromJson(v)); + }); + }, onFailure: (String error, int statusCode) { + throw error; + }, body: checkActivationCodeRequestModel.toJson()); return Future.value(localRes); } catch (error) { print(error); @@ -208,4 +213,21 @@ class AuthViewModel with ChangeNotifier { throw error; } } + + Future sendActivationCodeVerificationScreen( + ActivationCodeModel2 activationCodeModel) async { + try { + var localRes; + await baseAppClient.post(SEND_ACTIVATION_CODE_FOR_VERIFICATION_SCREEN, + onSuccess: (dynamic response, int statusCode) { + localRes = response; + }, onFailure: (String error, int statusCode) { + throw error; + }, body: activationCodeModel.toJson()); + return Future.value(localRes); + } catch (error) { + print(error); + throw error; + } + } } diff --git a/lib/core/viewModel/imei_view_model.dart b/lib/core/viewModel/imei_view_model.dart new file mode 100644 index 00000000..29253b1d --- /dev/null +++ b/lib/core/viewModel/imei_view_model.dart @@ -0,0 +1,21 @@ +import 'package:doctor_app_flutter/client/base_app_client.dart'; +import 'package:doctor_app_flutter/core/enum/viewstate.dart'; +import 'package:doctor_app_flutter/core/model/imei_details.dart'; +import 'package:doctor_app_flutter/core/service/auth_service.dart'; +import 'package:doctor_app_flutter/core/viewModel/base_view_model.dart'; +import 'package:doctor_app_flutter/locator.dart'; + +class IMEIViewModel extends BaseViewModel { + AuthService _authService = locator(); + List get imeiDetails => _authService.dashboardItemsList; + + Future selectDeviceImei(imei) async { + setState(ViewState.Busy); + await _authService.selectDeviceImei(imei); + if (_authService.hasError) { + error = _authService.error; + setState(ViewState.Error); + } else + setState(ViewState.Idle); + } +} diff --git a/lib/core/viewModel/patient-referral-viewmodel.dart b/lib/core/viewModel/patient-referral-viewmodel.dart index 35747c37..a1fc73fb 100644 --- a/lib/core/viewModel/patient-referral-viewmodel.dart +++ b/lib/core/viewModel/patient-referral-viewmodel.dart @@ -27,9 +27,27 @@ class PatientReferralViewModel extends BaseViewModel { List get pendingReferral => _referralPatientService.pendingReferralList; - List get patientArrivalList => + List get patientReferral => + _referralPatientService.patientReferralList; + + List get patientArrivalList => _referralPatientService.patientArrivalList; + Future getPatientReferral(PatiantInformtion patient) async { + setState(ViewState.Busy); + await _referralPatientService.getPatientReferral(patient); + if (_referralPatientService.hasError) { + error = _referralPatientService.error; + setState(ViewState.Error); + } else { + if(patientReferral.length == 0){ + await getMasterLookup(MasterKeysService.physiotherapyGoals); + } else { + setState(ViewState.Idle); + } + } + } + Future getMasterLookup(MasterKeysService masterKeys) async { setState(ViewState.Busy); await _referralPatientService.getMasterLookup(masterKeys); @@ -37,7 +55,7 @@ class PatientReferralViewModel extends BaseViewModel { error = _referralPatientService.error; setState(ViewState.Error); } else - await getBranches(); + await getBranches(); } Future getBranches() async { diff --git a/lib/core/viewModel/patient-vital-sign-viewmodel.dart b/lib/core/viewModel/patient-vital-sign-viewmodel.dart index 4f2e7e28..4e656d6d 100644 --- a/lib/core/viewModel/patient-vital-sign-viewmodel.dart +++ b/lib/core/viewModel/patient-vital-sign-viewmodel.dart @@ -4,6 +4,7 @@ import 'package:doctor_app_flutter/core/viewModel/base_view_model.dart'; import 'package:doctor_app_flutter/models/patient/PatientArrivalEntity.dart'; import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart'; import 'package:doctor_app_flutter/models/patient/vital_sign/patient-vital-sign-data.dart'; +import 'package:doctor_app_flutter/models/patient/vital_sign/patient-vital-sign-history.dart'; import 'package:doctor_app_flutter/models/patient/vital_sign/vital_sign_res_model.dart'; import '../../locator.dart'; @@ -11,10 +12,16 @@ import '../../locator.dart'; class VitalSignsViewModel extends BaseViewModel { VitalSignsService _vitalSignService = locator(); - List get patientArrivalList => - _vitalSignService.patientArrivalList; - VitalSignData get patientVitalSigns => _vitalSignService.patientVitalSigns; + List get patientVitalSignsHistory => _vitalSignService.patientVitalSignsHistory; + + String heightCm = "0"; + String weightKg = "0"; + String bodyMax = "0"; + String temperatureCelcius = "0"; + String hartRat = "0"; + String respirationBeatPerMinute = "0"; + String bloodPressure = "0 / 0"; Future getPatientVitalSign(PatiantInformtion patient) async { setState(ViewState.Busy); @@ -23,47 +30,51 @@ class VitalSignsViewModel extends BaseViewModel { error = _vitalSignService.error; setState(ViewState.Error); } else { - // if (patientVitalSigns == null) { - // makeVitalSignDemoData(); - // } setState(ViewState.Idle); } } - makeVitalSignDemoData(){ - _vitalSignService.patientVitalSigns = VitalSignData( - appointmentNo: 2016053265, - bloodPressureCuffLocation: 0, - bloodPressureCuffSize: 0, - bloodPressureHigher: 38, - bloodPressureLower: 32, - bloodPressurePatientPosition: 1, - bodyMassIndex: 31.11, - fio2: 0, - headCircumCm: 0, - heightCm: 150, - idealBodyWeightLbs: -2, - isPainManagementDone: false, - isVitalsRequired: true, - leanBodyWeightLbs: 0, - painCharacter: null, - painDuration: null, - painFrequency: null, - painLocation: null, - painScore: 0, - patientMRN: 3333274, - patientType: 1, - pulseBeatPerMinute: 0, - pulseRhythm: 0, - respirationBeatPerMinute: 0, - respirationPattern: 0, - sao2: 0, - status: 47, - temperatureCelcius: 40, - temperatureCelciusMethod: 1, - waistSizeInch: 39, - weightKg: 70, - ); + Future getPatientVitalSignHistory(PatiantInformtion patient, String from, String to) async { + setState(ViewState.Busy); + await _vitalSignService.getPatientVitalSignsHistory(patient, from, to); + if (_vitalSignService.hasError) { + error = _vitalSignService.error; + setState(ViewState.Error); + } else { + patientVitalSignsHistory.forEach((element) { + if (heightCm == "0" || heightCm == null || heightCm == 'null') { + heightCm = element.heightCm.toString(); + } + if (weightKg == "0" || weightKg == null || weightKg == 'null') { + weightKg = element.weightKg.toString(); + } + if (bodyMax == "0" || + bodyMax == null || + bodyMax == 'null') { + bodyMax = element.bodyMassIndex.toString(); + } + if (temperatureCelcius == "0" || + temperatureCelcius == null || + temperatureCelcius == 'null') { + temperatureCelcius = element.temperatureCelcius.toString(); + } + if (hartRat == "0" || hartRat == null || hartRat == 'null') { + hartRat = element.pulseBeatPerMinute.toString(); + } + if (respirationBeatPerMinute == "0" || + respirationBeatPerMinute == null || + respirationBeatPerMinute == 'null') { + respirationBeatPerMinute = + element.respirationBeatPerMinute.toString(); + } + if (bloodPressure == "0 / 0" || + bloodPressure == null || + bloodPressure == 'null') { + bloodPressure = element.bloodPressure.toString(); + } + }); + setState(ViewState.Idle); + } } String getBMI(var bodyMassIndex) { diff --git a/lib/core/viewModel/prescription_view_model.dart b/lib/core/viewModel/prescription_view_model.dart index 3380d8c2..d7b8f409 100644 --- a/lib/core/viewModel/prescription_view_model.dart +++ b/lib/core/viewModel/prescription_view_model.dart @@ -5,6 +5,9 @@ import 'package:doctor_app_flutter/core/model/search_drug_model.dart'; import 'package:doctor_app_flutter/core/service/prescription_service.dart'; import 'package:doctor_app_flutter/core/viewModel/base_view_model.dart'; import 'package:doctor_app_flutter/locator.dart'; +import 'package:doctor_app_flutter/models/SOAP/GetAllergiesResModel.dart'; +import 'package:doctor_app_flutter/models/SOAP/master_key_model.dart'; +import 'package:doctor_app_flutter/models/patient/vital_sign/patient-vital-sign-data.dart'; class PrescriptionViewModel extends BaseViewModel { bool hasError = false; @@ -67,4 +70,16 @@ class PrescriptionViewModel extends BaseViewModel { } else setState(ViewState.Idle); } + + Future getDrugToDrug( + VitalSignData vital, List allergy) async { + hasError = false; + setState(ViewState.Busy); + await _prescriptionService.getDrugToDrug(vital, allergy); + if (_prescriptionService.hasError) { + error = _prescriptionService.error; + setState(ViewState.ErrorLocal); + } else + setState(ViewState.Idle); + } } diff --git a/lib/core/viewModel/project_view_model.dart b/lib/core/viewModel/project_view_model.dart index 1448fb47..aed67d83 100644 --- a/lib/core/viewModel/project_view_model.dart +++ b/lib/core/viewModel/project_view_model.dart @@ -24,6 +24,7 @@ class ProjectViewModel with ChangeNotifier { List doctorClinicsList = []; bool isLoading = false; bool isError = false; + bool isLogin = false; String error = ''; BaseAppClient baseAppClient = BaseAppClient(); @@ -56,7 +57,9 @@ class ProjectViewModel with ChangeNotifier { currentLanguage = await sharedPref.getString(APP_Language); _appLocale = Locale(currentLanguage ?? 'en'); _isArabic = currentLanguage != null - ? currentLanguage == 'ar' ? true : false + ? currentLanguage == 'ar' + ? true + : false : false; notifyListeners(); } @@ -69,7 +72,7 @@ class ProjectViewModel with ChangeNotifier { sharedPref.setString(APP_Language, 'ar'); } else if (lan != "ar" && currentLanguage != lan) { _appLocale = Locale("en"); - _isArabic = false; + _isArabic = false; currentLanguage = 'en'; sharedPref.setString(APP_Language, 'en'); } diff --git a/lib/landing_page.dart b/lib/landing_page.dart index 9d4bfbb0..c5494acf 100644 --- a/lib/landing_page.dart +++ b/lib/landing_page.dart @@ -64,10 +64,9 @@ class _LandingPageState extends State { ShowCaseWidget( builder: Builder(builder: (context) => DashboardScreen()), ), - MessagesScreen(), + // MessagesScreen(), MyScheduleScreen(), - //NewPrescriptionScreen(), - ServicesScreen() + // ServicesScreen() ], ), bottomNavigationBar: BottomNavBar(changeIndex: _changeCurrentTab), diff --git a/lib/locator.dart b/lib/locator.dart index a4ca7289..f939effc 100644 --- a/lib/locator.dart +++ b/lib/locator.dart @@ -1,10 +1,13 @@ +import 'package:doctor_app_flutter/core/service/auth_service.dart'; import 'package:doctor_app_flutter/core/service/dasboard_service.dart'; import 'package:doctor_app_flutter/core/service/medical_file_service.dart'; import 'package:doctor_app_flutter/core/service/patient_service.dart'; import 'package:doctor_app_flutter/core/service/prescription_service.dart'; import 'package:doctor_app_flutter/core/service/procedure_service.dart'; import 'package:doctor_app_flutter/core/service/sickleave_service.dart'; +import 'package:doctor_app_flutter/core/viewModel/auth_view_model.dart'; import 'package:doctor_app_flutter/core/viewModel/dashboard_view_model.dart'; +import 'package:doctor_app_flutter/core/viewModel/imei_view_model.dart'; import 'package:doctor_app_flutter/core/viewModel/medical_file_view_model.dart'; import 'package:doctor_app_flutter/core/viewModel/patient_view_model.dart'; import 'package:doctor_app_flutter/core/viewModel/prescription_view_model.dart'; @@ -54,9 +57,11 @@ void setupLocator() { locator.registerLazySingleton(() => MedicalFileService()); locator.registerLazySingleton(() => AdmissionRequestService()); locator.registerLazySingleton(() => UcafService()); + locator.registerLazySingleton(() => AuthService()); /// View Model locator.registerFactory(() => DoctorReplayViewModel()); + locator.registerFactory(() => IMEIViewModel()); locator.registerFactory(() => ScheduleViewModel()); locator.registerFactory(() => ReferralPatientViewModel()); locator.registerFactory(() => ReferredPatientViewModel()); diff --git a/lib/lookups/patient_lookup.dart b/lib/lookups/patient_lookup.dart index dfcaa305..fa75abaa 100644 --- a/lib/lookups/patient_lookup.dart +++ b/lib/lookups/patient_lookup.dart @@ -27,11 +27,14 @@ const LOCATIONS = const [ ]; enum vitalSignDetails { - bodyMeasurements, - temperature, - pulse, - pespiration, - bloodPressure, - oxygenation, - painScale + BodyMeasurements, + Temperature, + Pulse, + Prescriptions, + BloodPressure, + Respiration, + heart, + PainScale, + Weight, + Height } diff --git a/lib/main.dart b/lib/main.dart index 3df44a70..1283da1e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -41,32 +41,31 @@ class MyApp extends StatelessWidget { ), ], child: Consumer( - builder: (context,projectProvider,child) => MaterialApp( - showSemanticsDebugger: false, - title: 'Flutter Demo', - locale: projectProvider.appLocal, - localizationsDelegates: [ - TranslationBaseDelegate(), - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - ], - supportedLocales: [ - const Locale('ar', ''), // Arabic - const Locale('en', ''), // English - ], - theme: ThemeData( - primarySwatch: Colors.grey, - primaryColor: Colors.grey, - buttonColor: HexColor('#B8382C'), - fontFamily: 'WorkSans', - dividerColor: Colors.grey[350], - backgroundColor: Color.fromRGBO(255,255,255, 1), - ), - initialRoute: INIT_ROUTE, - routes: routes, - debugShowCheckedModeBanner: false, - ) - ), + builder: (context, projectProvider, child) => MaterialApp( + showSemanticsDebugger: false, + title: 'Flutter Demo', + locale: projectProvider.appLocal, + localizationsDelegates: [ + TranslationBaseDelegate(), + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ], + supportedLocales: [ + const Locale('ar', ''), // Arabic + const Locale('en', ''), // English + ], + theme: ThemeData( + primarySwatch: Colors.grey, + primaryColor: Colors.grey, + buttonColor: HexColor('#B8382C'), + fontFamily: 'WorkSans', + dividerColor: Colors.grey[350], + backgroundColor: Color.fromRGBO(255, 255, 255, 1), + ), + initialRoute: INIT_ROUTE, + routes: routes, + debugShowCheckedModeBanner: false, + )), ); }); }, diff --git a/lib/models/SOAP/PostEpisodeReqModel.dart b/lib/models/SOAP/PostEpisodeReqModel.dart new file mode 100644 index 00000000..6d3ee45a --- /dev/null +++ b/lib/models/SOAP/PostEpisodeReqModel.dart @@ -0,0 +1,28 @@ +class PostEpisodeReqModel { + int appointmentNo; + int patientMRN; + int doctorID; + String vidaAuthTokenID; + + PostEpisodeReqModel( + {this.appointmentNo, + this.patientMRN, + this.doctorID, + this.vidaAuthTokenID}); + + PostEpisodeReqModel.fromJson(Map json) { + appointmentNo = json['AppointmentNo']; + patientMRN = json['PatientMRN']; + doctorID = json['DoctorID']; + vidaAuthTokenID = json['VidaAuthTokenID']; + } + + Map toJson() { + final Map data = new Map(); + data['AppointmentNo'] = this.appointmentNo; + data['PatientMRN'] = this.patientMRN; + data['DoctorID'] = this.doctorID; + data['VidaAuthTokenID'] = this.vidaAuthTokenID; + return data; + } +} diff --git a/lib/models/auth/activation_Code_req_model.dart b/lib/models/auth/activation_Code_req_model.dart index f8f48cd8..1a9510e8 100644 --- a/lib/models/auth/activation_Code_req_model.dart +++ b/lib/models/auth/activation_Code_req_model.dart @@ -8,17 +8,18 @@ class ActivationCodeModel { String password; int facilityId; String generalid; - + String otpSendType; ActivationCodeModel( {this.mobileNumber, - this.zipCode, - this.channel, - this.languageID, - this.versionID, - this.memberID, - this.password, - this.facilityId, - this.generalid}); + this.zipCode, + this.channel, + this.languageID, + this.versionID, + this.memberID, + this.password, + this.facilityId, + this.otpSendType, + this.generalid}); ActivationCodeModel.fromJson(Map json) { mobileNumber = json['MobileNumber']; @@ -29,6 +30,7 @@ class ActivationCodeModel { memberID = json['MemberID']; password = json['Password']; facilityId = json['facilityId']; + otpSendType = json['OTP_SendType']; generalid = json['generalid']; } @@ -42,6 +44,7 @@ class ActivationCodeModel { data['MemberID'] = this.memberID; data['Password'] = this.password; data['facilityId'] = this.facilityId; + data['OTP_SendType'] = otpSendType; data['generalid'] = this.generalid; return data; } diff --git a/lib/models/auth/check_activation_code_request_model.dart b/lib/models/auth/check_activation_code_request_model.dart index 856f1c43..9bb3d4f6 100644 --- a/lib/models/auth/check_activation_code_request_model.dart +++ b/lib/models/auth/check_activation_code_request_model.dart @@ -12,21 +12,22 @@ class CheckActivationCodeRequestModel { String activationCode; String vidaAuthTokenID; String vidaRefreshTokenID; - + int oTPSendType; CheckActivationCodeRequestModel( {this.mobileNumber, - this.zipCode, - this.doctorID, - this.iPAdress, - this.channel, - this.languageID, - this.projectID, - this.versionID, - this.generalid, - this.logInTokenID, - this.activationCode, - this.vidaAuthTokenID, - this.vidaRefreshTokenID}); + this.zipCode, + this.doctorID, + this.iPAdress, + this.channel, + this.languageID, + this.projectID, + this.versionID, + this.generalid, + this.logInTokenID, + this.activationCode, + this.vidaAuthTokenID, + this.vidaRefreshTokenID, + this.oTPSendType}); CheckActivationCodeRequestModel.fromJson(Map json) { mobileNumber = json['MobileNumber']; @@ -42,6 +43,7 @@ class CheckActivationCodeRequestModel { activationCode = json['activationCode']; vidaAuthTokenID = json['VidaAuthTokenID']; vidaRefreshTokenID = json['VidaRefreshTokenID']; + oTPSendType = json['OTP_SendType']; } Map toJson() { @@ -59,6 +61,7 @@ class CheckActivationCodeRequestModel { data['activationCode'] = this.activationCode; data['VidaAuthTokenID'] = this.vidaAuthTokenID; data['VidaRefreshTokenID'] = this.vidaRefreshTokenID; + data['OTP_SendType'] = this.oTPSendType; return data; } } diff --git a/lib/models/auth/send_activation_code_model2.dart b/lib/models/auth/send_activation_code_model2.dart new file mode 100644 index 00000000..794887b3 --- /dev/null +++ b/lib/models/auth/send_activation_code_model2.dart @@ -0,0 +1,60 @@ +class ActivationCodeModel2 { + int oTPSendType; + String mobileNumber; + String zipCode; + int channel; + int languageID; + double versionID; + int memberID; + int facilityId; + String generalid; + int isMobileFingerPrint; + String vidaAuthTokenID; + String vidaRefreshTokenID; + + ActivationCodeModel2( + {this.oTPSendType, + this.mobileNumber, + this.zipCode, + this.channel, + this.languageID, + this.versionID, + this.memberID, + this.facilityId, + this.generalid, + this.isMobileFingerPrint, + this.vidaAuthTokenID, + this.vidaRefreshTokenID}); + + ActivationCodeModel2.fromJson(Map json) { + oTPSendType = json['OTP_SendType']; + mobileNumber = json['MobileNumber']; + zipCode = json['ZipCode']; + channel = json['Channel']; + languageID = json['LanguageID']; + versionID = json['VersionID']; + memberID = json['MemberID']; + facilityId = json['facilityId']; + generalid = json['generalid']; + isMobileFingerPrint = json['IsMobileFingerPrint']; + vidaAuthTokenID = json['VidaAuthTokenID']; + vidaRefreshTokenID = json['VidaRefreshTokenID']; + } + + Map toJson() { + final Map data = new Map(); + data['OTP_SendType'] = this.oTPSendType; + data['MobileNumber'] = this.mobileNumber; + data['ZipCode'] = this.zipCode; + data['Channel'] = this.channel; + data['LanguageID'] = this.languageID; + data['VersionID'] = this.versionID; + data['MemberID'] = this.memberID; + data['facilityId'] = this.facilityId; + data['generalid'] = this.generalid; + data['IsMobileFingerPrint'] = this.isMobileFingerPrint; + data['VidaAuthTokenID'] = this.vidaAuthTokenID; + data['VidaRefreshTokenID'] = this.vidaRefreshTokenID; + return data; + } +} diff --git a/lib/models/patient/vital_sign/patient-vital-sign-data.dart b/lib/models/patient/vital_sign/patient-vital-sign-data.dart index c5e503c2..b7fe77cb 100644 --- a/lib/models/patient/vital_sign/patient-vital-sign-data.dart +++ b/lib/models/patient/vital_sign/patient-vital-sign-data.dart @@ -33,36 +33,36 @@ class VitalSignData { VitalSignData( {this.appointmentNo, - this.bloodPressureCuffLocation, - this.bloodPressureCuffSize, - this.bloodPressureHigher, - this.bloodPressureLower, - this.bloodPressurePatientPosition, - this.bodyMassIndex, - this.fio2, - this.headCircumCm, - this.heightCm, - this.idealBodyWeightLbs, - this.isPainManagementDone, - this.isVitalsRequired, - this.leanBodyWeightLbs, - this.painCharacter, - this.painDuration, - this.painFrequency, - this.painLocation, - this.painScore, - this.patientMRN, - this.patientType, - this.pulseBeatPerMinute, - this.pulseRhythm, - this.respirationBeatPerMinute, - this.respirationPattern, - this.sao2, - this.status, - this.temperatureCelcius, - this.temperatureCelciusMethod, - this.waistSizeInch, - this.weightKg}); + this.bloodPressureCuffLocation, + this.bloodPressureCuffSize, + this.bloodPressureHigher, + this.bloodPressureLower, + this.bloodPressurePatientPosition, + this.bodyMassIndex, + this.fio2, + this.headCircumCm, + this.heightCm, + this.idealBodyWeightLbs, + this.isPainManagementDone, + this.isVitalsRequired, + this.leanBodyWeightLbs, + this.painCharacter, + this.painDuration, + this.painFrequency, + this.painLocation, + this.painScore, + this.patientMRN, + this.patientType, + this.pulseBeatPerMinute, + this.pulseRhythm, + this.respirationBeatPerMinute, + this.respirationPattern, + this.sao2, + this.status, + this.temperatureCelcius, + this.temperatureCelciusMethod, + this.waistSizeInch, + this.weightKg}); VitalSignData.fromJson(Map json) { appointmentNo = json['appointmentNo']; @@ -133,4 +133,5 @@ class VitalSignData { data['weightKg'] = this.weightKg; return data; } + } diff --git a/lib/models/patient/vital_sign/patient-vital-sign-history.dart b/lib/models/patient/vital_sign/patient-vital-sign-history.dart new file mode 100644 index 00000000..40ff5d00 --- /dev/null +++ b/lib/models/patient/vital_sign/patient-vital-sign-history.dart @@ -0,0 +1,257 @@ +class VitalSignHistory { + var transNo; + var projectID; + var weightKg; + var heightCm; + var temperatureCelcius; + var pulseBeatPerMinute; + var respirationBeatPerMinute; + var bloodPressureLower; + var bloodPressureHigher; + var sAO2; + var fIO2; + var painScore; + var bodyMassIndex; + var headCircumCm; + var leanBodyWeightLbs; + var idealBodyWeightLbs; + var temperatureCelciusMethod; + var pulseRhythm; + var respirationPattern; + var bloodPressureCuffLocation; + var bloodPressureCuffSize; + var bloodPressurePatientPosition; + var painLocation; + var painDuration; + var painCharacter; + var painFrequency; + bool isPainManagementDone; + var status; + bool isVitalsRequired; + var patientID; + var createdOn; + var doctorID; + var clinicID; + var triageCategory; + var gCScore; + var lineItemNo; + DateTime vitalSignDate; + var actualTimeTaken; + var sugarLevel; + var fBS; + var rBS; + var observationType; + var heartRate; + var muscleTone; + var reflexIrritability; + var bodyColor; + var isFirstAssessment; + var dateofBirth; + var timeOfBirth; + var bloodPressure; + var bloodPressureCuffLocationDesc; + var bloodPressureCuffSizeDesc; + var bloodPressurePatientPositionDesc; + var clinicName; + var doctorImageURL; + var doctorName; + var painScoreDesc; + var pulseRhythmDesc; + var respirationPatternDesc; + var temperatureCelciusMethodDesc; + var time; + + VitalSignHistory( + {this.transNo, + this.projectID, + this.weightKg, + this.heightCm, + this.temperatureCelcius, + this.pulseBeatPerMinute, + this.respirationBeatPerMinute, + this.bloodPressureLower, + this.bloodPressureHigher, + this.sAO2, + this.fIO2, + this.painScore, + this.bodyMassIndex, + this.headCircumCm, + this.leanBodyWeightLbs, + this.idealBodyWeightLbs, + this.temperatureCelciusMethod, + this.pulseRhythm, + this.respirationPattern, + this.bloodPressureCuffLocation, + this.bloodPressureCuffSize, + this.bloodPressurePatientPosition, + this.painLocation, + this.painDuration, + this.painCharacter, + this.painFrequency, + this.isPainManagementDone, + this.status, + this.isVitalsRequired, + this.patientID, + this.createdOn, + this.doctorID, + this.clinicID, + this.triageCategory, + this.gCScore, + this.lineItemNo, + this.vitalSignDate, + this.actualTimeTaken, + this.sugarLevel, + this.fBS, + this.rBS, + this.observationType, + this.heartRate, + this.muscleTone, + this.reflexIrritability, + this.bodyColor, + this.isFirstAssessment, + this.dateofBirth, + this.timeOfBirth, + this.bloodPressure, + this.bloodPressureCuffLocationDesc, + this.bloodPressureCuffSizeDesc, + this.bloodPressurePatientPositionDesc, + this.clinicName, + this.doctorImageURL, + this.doctorName, + this.painScoreDesc, + this.pulseRhythmDesc, + this.respirationPatternDesc, + this.temperatureCelciusMethodDesc, + this.time}); + + VitalSignHistory.fromJson(Map json) { + transNo = json['TransNo']; + projectID = json['ProjectID']; + weightKg = json['WeightKg']; + heightCm = json['HeightCm']; + temperatureCelcius = json['TemperatureCelcius']; + pulseBeatPerMinute = json['PulseBeatPerMinute']; + respirationBeatPerMinute = json['RespirationBeatPerMinute']; + bloodPressureLower = json['BloodPressureLower']; + bloodPressureHigher = json['BloodPressureHigher']; + sAO2 = json['SAO2']; + fIO2 = json['FIO2']; + painScore = json['PainScore']; + bodyMassIndex = json['BodyMassIndex']; + headCircumCm = json['HeadCircumCm']; + leanBodyWeightLbs = json['LeanBodyWeightLbs']; + idealBodyWeightLbs = json['IdealBodyWeightLbs']; + temperatureCelciusMethod = json['TemperatureCelciusMethod']; + pulseRhythm = json['PulseRhythm']; + respirationPattern = json['RespirationPattern']; + bloodPressureCuffLocation = json['BloodPressureCuffLocation']; + bloodPressureCuffSize = json['BloodPressureCuffSize']; + bloodPressurePatientPosition = json['BloodPressurePatientPosition']; + painLocation = json['PainLocation']; + painDuration = json['PainDuration']; + painCharacter = json['PainCharacter']; + painFrequency = json['PainFrequency']; + isPainManagementDone = json['IsPainManagementDone']; + status = json['Status']; + isVitalsRequired = json['IsVitalsRequired']; + patientID = json['PatientID']; + createdOn = json['CreatedOn']; + doctorID = json['DoctorID']; + clinicID = json['ClinicID']; + triageCategory = json['TriageCategory']; + gCScore = json['GCScore']; + lineItemNo = json['LineItemNo']; + vitalSignDate = json['VitalSignDate']; + actualTimeTaken = json['ActualTimeTaken']; + sugarLevel = json['SugarLevel']; + fBS = json['FBS']; + rBS = json['RBS']; + observationType = json['ObservationType']; + heartRate = json['HeartRate']; + muscleTone = json['MuscleTone']; + reflexIrritability = json['ReflexIrritability']; + bodyColor = json['BodyColor']; + isFirstAssessment = json['IsFirstAssessment']; + dateofBirth = json['DateofBirth']; + timeOfBirth = json['TimeOfBirth']; + bloodPressure = json['BloodPressure']; + bloodPressureCuffLocationDesc = json['BloodPressureCuffLocationDesc']; + bloodPressureCuffSizeDesc = json['BloodPressureCuffSizeDesc']; + bloodPressurePatientPositionDesc = json['BloodPressurePatientPositionDesc']; + clinicName = json['ClinicName']; + doctorImageURL = json['DoctorImageURL']; + doctorName = json['DoctorName']; + painScoreDesc = json['PainScoreDesc']; + pulseRhythmDesc = json['PulseRhythmDesc']; + respirationPatternDesc = json['RespirationPatternDesc']; + temperatureCelciusMethodDesc = json['TemperatureCelciusMethodDesc']; + time = json['Time']; + } + + Map toJson() { + final Map data = new Map(); + data['TransNo'] = this.transNo; + data['ProjectID'] = this.projectID; + data['WeightKg'] = this.weightKg; + data['HeightCm'] = this.heightCm; + data['TemperatureCelcius'] = this.temperatureCelcius; + data['PulseBeatPerMinute'] = this.pulseBeatPerMinute; + data['RespirationBeatPerMinute'] = this.respirationBeatPerMinute; + data['BloodPressureLower'] = this.bloodPressureLower; + data['BloodPressureHigher'] = this.bloodPressureHigher; + data['SAO2'] = this.sAO2; + data['FIO2'] = this.fIO2; + data['PainScore'] = this.painScore; + data['BodyMassIndex'] = this.bodyMassIndex; + data['HeadCircumCm'] = this.headCircumCm; + data['LeanBodyWeightLbs'] = this.leanBodyWeightLbs; + data['IdealBodyWeightLbs'] = this.idealBodyWeightLbs; + data['TemperatureCelciusMethod'] = this.temperatureCelciusMethod; + data['PulseRhythm'] = this.pulseRhythm; + data['RespirationPattern'] = this.respirationPattern; + data['BloodPressureCuffLocation'] = this.bloodPressureCuffLocation; + data['BloodPressureCuffSize'] = this.bloodPressureCuffSize; + data['BloodPressurePatientPosition'] = this.bloodPressurePatientPosition; + data['PainLocation'] = this.painLocation; + data['PainDuration'] = this.painDuration; + data['PainCharacter'] = this.painCharacter; + data['PainFrequency'] = this.painFrequency; + data['IsPainManagementDone'] = this.isPainManagementDone; + data['Status'] = this.status; + data['IsVitalsRequired'] = this.isVitalsRequired; + data['PatientID'] = this.patientID; + data['CreatedOn'] = this.createdOn; + data['DoctorID'] = this.doctorID; + data['ClinicID'] = this.clinicID; + data['TriageCategory'] = this.triageCategory; + data['GCScore'] = this.gCScore; + data['LineItemNo'] = this.lineItemNo; + data['VitalSignDate'] = this.vitalSignDate; + data['ActualTimeTaken'] = this.actualTimeTaken; + data['SugarLevel'] = this.sugarLevel; + data['FBS'] = this.fBS; + data['RBS'] = this.rBS; + data['ObservationType'] = this.observationType; + data['HeartRate'] = this.heartRate; + data['MuscleTone'] = this.muscleTone; + data['ReflexIrritability'] = this.reflexIrritability; + data['BodyColor'] = this.bodyColor; + data['IsFirstAssessment'] = this.isFirstAssessment; + data['DateofBirth'] = this.dateofBirth; + data['TimeOfBirth'] = this.timeOfBirth; + data['BloodPressure'] = this.bloodPressure; + data['BloodPressureCuffLocationDesc'] = this.bloodPressureCuffLocationDesc; + data['BloodPressureCuffSizeDesc'] = this.bloodPressureCuffSizeDesc; + data['BloodPressurePatientPositionDesc'] = + this.bloodPressurePatientPositionDesc; + data['ClinicName'] = this.clinicName; + data['DoctorImageURL'] = this.doctorImageURL; + data['DoctorName'] = this.doctorName; + data['PainScoreDesc'] = this.painScoreDesc; + data['PulseRhythmDesc'] = this.pulseRhythmDesc; + data['RespirationPatternDesc'] = this.respirationPatternDesc; + data['TemperatureCelciusMethodDesc'] = this.temperatureCelciusMethodDesc; + data['Time'] = this.time; + return data; + } +} diff --git a/lib/routes.dart b/lib/routes.dart index e57b56a7..8f2b08a4 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -85,9 +85,9 @@ const String PATIENT_ORDERS = 'patients/patient_orders'; const String PATIENT_INSURANCE_APPROVALS = 'patients/patient_insurance_approvals'; const String VITAL_SIGN_DETAILS = 'patients/vital-sign-details'; +const String PATIENT_VITAL_SIGN = 'patients/vital-sign-data'; const String CREATE_EPISODE = 'patients/create-episode'; const String UPDATE_EPISODE = 'patients/update-episode'; -const String PATIENT_VITAL_SIGN = 'patients/vital-sign-data'; const String PATIENT_ADMISSION_REQUEST = 'patients/admission-request'; const String PATIENT_ADMISSION_REQUEST_2 = 'patients/admission-request-second'; const String PATIENT_ADMISSION_REQUEST_3 = 'patients/admission-request-third'; diff --git a/lib/screens/auth/login_screen.dart b/lib/screens/auth/login_screen.dart index 5b495abb..1ed441e4 100644 --- a/lib/screens/auth/login_screen.dart +++ b/lib/screens/auth/login_screen.dart @@ -1,7 +1,17 @@ import 'dart:async'; +import 'dart:io'; import 'package:doctor_app_flutter/config/config.dart'; +import 'package:doctor_app_flutter/config/shared_pref_kay.dart'; +import 'package:doctor_app_flutter/core/service/auth_service.dart'; +import 'package:doctor_app_flutter/core/viewModel/auth_view_model.dart'; +import 'package:doctor_app_flutter/core/viewModel/imei_view_model.dart'; +import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; +import 'package:doctor_app_flutter/screens/auth/verification_methods_screen.dart'; +import 'package:doctor_app_flutter/screens/base/base_view.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../lookups/auth_lookup.dart'; @@ -23,21 +33,48 @@ class _LoginsreenState extends State { Future _prefs = SharedPreferences.getInstance(); String platformImei; - Future platformImeiFuture; - - bool _isLoading = false; - - Future getSharedPref() async { - sharedPref.getString('platformImei').then((imei) { - platformImei = imei; - }); - } - + // Future platformImeiFuture; + final FirebaseMessaging _firebaseMessaging = FirebaseMessaging(); + bool _isLoading = true; + ProjectViewModel projectViewModel; + AuthService authService = AuthService(); @override void initState() { super.initState(); - platformImeiFuture = _prefs.then((SharedPreferences prefs) { - return (prefs.getString('platformImei')); + + _firebaseMessaging.setAutoInitEnabled(true); + if (Platform.isIOS) { + _firebaseMessaging.requestNotificationPermissions(); + } + + _firebaseMessaging.getToken().then((String token) async { + if (DEVICE_TOKEN == "" && projectViewModel.isLogin == false) { + DEVICE_TOKEN = token; + changeLoadingStata(true); + authService.selectDeviceImei(DEVICE_TOKEN).then((value) { + print(authService.dashboardItemsList); + + if (authService.dashboardItemsList.length > 0) { + sharedPref.setObj( + LAST_LOGIN_USER, authService.dashboardItemsList[0]); + Navigator.of(context).pushReplacement(MaterialPageRoute( + builder: (BuildContext context) => VerificationMethodsScreen( + password: null, + ))); + } else { + changeLoadingStata(false); + } + //changeLoadingStata(false); + }); + } else { + changeLoadingStata(false); + } + + // else if (projectViewModel.isLogin) { + // getNotificationCount(token); + // } + }).catchError((err) { + print(err); }); } @@ -56,54 +93,46 @@ class _LoginsreenState extends State { @override Widget build(BuildContext context) { - getSharedPref(); - return AppScaffold( - isLoading: _isLoading, - isShowAppBar: false, - body: SafeArea( - child: ListView(children: [ - FutureBuilder( - future: platformImeiFuture, - builder: (BuildContext context, AsyncSnapshot snapshot) { - switch (snapshot.connectionState) { - case ConnectionState.waiting: - return DrAppCircularProgressIndeicator(); - default: - if (snapshot.hasError) { - return Text('Error: ${snapshot.error}'); - } else { - return Container( - margin: EdgeInsetsDirectional.fromSTEB(30, 0, 30, 30), - alignment: Alignment.topLeft, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - (platformImei == null) - ? Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - AuthHeader(loginType.knownUser), - LoginForm( - changeLoadingStata: - changeLoadingStata, - ), - ], - ) - : Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - AuthHeader(loginType.unknownUser), - KnownUserLogin(), - ], + projectViewModel = Provider.of(context); + + return BaseView( + onModelReady: (model) => {}, + builder: (_, model, w) => AppScaffold( + baseViewModel: model, + isShowAppBar: false, + body: SafeArea( + child: (_isLoading == false) + ? ListView(children: [ + Container( + margin: + EdgeInsetsDirectional.fromSTEB(30, 0, 30, 30), + alignment: Alignment.topLeft, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + AuthHeader(loginType.knownUser), + LoginForm( + changeLoadingStata: changeLoadingStata, ), - ])); - } - } - }), - ]), - ), - ); + ], + ) + + // : Column( + // crossAxisAlignment: + // CrossAxisAlignment.start, + // children: [ + // AuthHeader(loginType.unknownUser), + // KnownUserLogin(), + // ], + // ), + ])) + ]) + : Center(child: CircularProgressIndicator()), + ), + )); } } diff --git a/lib/screens/auth/verification_methods_screen.dart b/lib/screens/auth/verification_methods_screen.dart index 2b411dc0..0045f032 100644 --- a/lib/screens/auth/verification_methods_screen.dart +++ b/lib/screens/auth/verification_methods_screen.dart @@ -42,7 +42,7 @@ class _VerificationMethodsScreenState extends State { Widget build(BuildContext context) { return AppScaffold( isLoading: _isLoading, - isShowAppBar: false, + isShowAppBar: false, body: ListView(children: [ Container( margin: EdgeInsetsDirectional.fromSTEB(30, 0, 30, 0), diff --git a/lib/screens/dashboard_screen.dart b/lib/screens/dashboard_screen.dart index 7187641d..7277bf32 100644 --- a/lib/screens/dashboard_screen.dart +++ b/lib/screens/dashboard_screen.dart @@ -1,3 +1,4 @@ +import 'package:doctor_app_flutter/config/config.dart'; import 'package:doctor_app_flutter/config/shared_pref_kay.dart'; import 'package:doctor_app_flutter/config/size_config.dart'; import 'package:doctor_app_flutter/core/viewModel/dashboard_view_model.dart'; @@ -9,14 +10,17 @@ import 'package:doctor_app_flutter/models/doctor/profile_req_Model.dart'; import 'package:doctor_app_flutter/core/viewModel/auth_view_model.dart'; import 'package:doctor_app_flutter/core/viewModel/hospital_view_model.dart'; import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; +import 'package:doctor_app_flutter/models/patient/patient_model.dart'; import 'package:doctor_app_flutter/screens/base/base_view.dart'; import 'package:doctor_app_flutter/screens/patients/profile/referral/my-referral-patient-screen.dart'; import 'package:doctor_app_flutter/screens/reschedule-leaves/add-rescheduleleave.dart'; +import 'package:doctor_app_flutter/util/date-utils.dart'; import 'package:doctor_app_flutter/util/dr_app_shared_pref.dart'; import 'package:doctor_app_flutter/util/helpers.dart'; import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; import 'package:doctor_app_flutter/widgets/patients/profile/profile-welcome-widget.dart'; import 'package:doctor_app_flutter/widgets/shared/app_scaffold_widget.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:hexcolor/hexcolor.dart'; @@ -45,6 +49,7 @@ class DashboardScreen extends StatefulWidget { } class _DashboardScreenState extends State { + final FirebaseMessaging _firebaseMessaging = FirebaseMessaging(); HospitalViewModel hospitalProvider; AuthViewModel authProvider; bool isLoading = false; @@ -58,6 +63,18 @@ class _DashboardScreenState extends State { if (_isInit) { projectsProvider = Provider.of(context); projectsProvider.getDoctorClinicsList(); + + _firebaseMessaging.setAutoInitEnabled(true); + _firebaseMessaging.getToken().then((String token) async { + if (token != '') { + DEVICE_TOKEN = token; + var request = await sharedPref.getObj(DOCTOR_PROFILE); + authProvider.insertDeviceImei(request).then((value) { + print(value['ReturnValue']); + changeIsLoading(false); + }); + } + }); } _isInit = false; } @@ -77,6 +94,27 @@ class _DashboardScreenState extends State { if (!currentFocus.hasPrimaryFocus) { currentFocus.unfocus(); } + + var _patientSearchFormValues = PatientModel( + FirstName: "0", + MiddleName: "0", + LastName: "0", + PatientMobileNumber: "0", + PatientIdentificationID: "0", + PatientID: 0, + From: DateUtils.convertDateToFormat(DateTime.now(), 'yyyy-MM-dd') + .toString(), + To: DateUtils.convertDateToFormat(DateTime.now(), 'yyyy-MM-dd') + .toString(), + LanguageID: 2, + stamp: "2020-03-02T13:56:39.170Z", + IPAdress: "11.11.11.11", + VersionID: 1.2, + Channel: 9, + TokenID: "2Fi7HoIHB0eDyekVa6tCJg==", + SessionID: "5G0yXn0Jnq", + IsLoginForDoctorApp: true, + PatientOutSA: false); return BaseView( //onModelReady: (model) => model.getDashboard(), builder: (_, model, w) => AppScaffold( @@ -649,7 +687,7 @@ class _DashboardScreenState extends State { AppText( model.dashboardItemsList.length > 0 ? getPatientCount( - model.dashboardItemsList[7]) + model.dashboardItemsList[5]) : "", fontSize: SizeConfig.textMultiplier * 6, color: Colors.white, @@ -693,7 +731,7 @@ class _DashboardScreenState extends State { color: Colors.white, ), AppText( - TranslationBase.of(context).radiology, + TranslationBase.of(context).clinic, color: Colors.white, ) ], @@ -957,6 +995,8 @@ class _DashboardScreenState extends State { height: 20, ), Row( + // mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.start, children: [ DashboardItem( child: Column( @@ -984,6 +1024,33 @@ class _DashboardScreenState extends State { ), ); }, + ), + SizedBox( + width: 8, + ), + DashboardItem( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Icon( + DoctorApp.patient, + size: 50, + ), + AppText( + TranslationBase.of(context).arrived, + color: Colors.black, + textAlign: TextAlign.center, + ) + ], + ), + hasBorder: true, + onTap: () { + Navigator.of(context) + .pushNamed(PATIENTS, arguments: { + "patientSearchForm": _patientSearchFormValues, + "selectedType": "7" + }); + }, ) ], ), diff --git a/lib/screens/patients/patient_search_screen.dart b/lib/screens/patients/patient_search_screen.dart index 61eb5fcf..94102b1b 100644 --- a/lib/screens/patients/patient_search_screen.dart +++ b/lib/screens/patients/patient_search_screen.dart @@ -68,21 +68,9 @@ class _PatientSearchScreenState extends State { try { - - /* Map profile = await sharedPref.getObj(DOCTOR_PROFILE); - DoctorProfileModel doctorProfile = - new DoctorProfileModel.fromJson(profile)*/; if (_formKey.currentState.validate()) { _formKey.currentState.save(); - /* sharedPref.setString(SLECTED_PATIENT_TYPE, _selectedType); - String token = await sharedPref.getString(TOKEN); - - _patientSearchFormValues.TokenID = token; - _patientSearchFormValues.ProjectID = doctorProfile.projectID; //15 - _patientSearchFormValues.DoctorID = doctorProfile.doctorID; - _patientSearchFormValues.ClinicID = doctorProfile.clinicID;*/ - if ((_patientSearchFormValues.From == "0" || _patientSearchFormValues.To == "0") && _selectedType == "7") { diff --git a/lib/screens/patients/patients_screen.dart b/lib/screens/patients/patients_screen.dart index 602bd180..a8da28b9 100644 --- a/lib/screens/patients/patients_screen.dart +++ b/lib/screens/patients/patients_screen.dart @@ -274,7 +274,8 @@ class _PatientsScreenState extends State { .then((res) { setState(() { _isLoading = false; - if (res['MessageStatus'] == 1) { + + if (res != null && res['MessageStatus'] == 1) { if (val2 == 7) { if (res[SERVICES_PATIANT2[val2]] == null) { _isError = true; @@ -282,6 +283,9 @@ class _PatientsScreenState extends State { this.error = error.toString(); } else { var localList = []; + if(res["patientArrivalList"]["entityList"] == null){ + res["patientArrivalList"]["entityList"] = []; + } res["patientArrivalList"]["entityList"].forEach((v) { Map mergedPatient = { ...v, @@ -289,7 +293,6 @@ class _PatientsScreenState extends State { }; localList.add(mergedPatient); }); - print(localList.toString()); lItems = localList; } } else { @@ -301,7 +304,7 @@ class _PatientsScreenState extends State { _isError = false; } else { _isError = true; - error = res['ErrorEndUserMessage'] ?? res['ErrorMessage']; + error = model.error; //res['ErrorEndUserMessage'] ?? res['ErrorMessage']; } }); }).catchError((error) { @@ -673,7 +676,9 @@ class _PatientsScreenState extends State { PATIENTS_PROFILE, arguments: { "patient": item, - "patientType":patientType + "patientType":patientType, + "from" : patient.getFrom, + "to" : patient.getTo, }); }, ), diff --git a/lib/screens/patients/profile/UCAF/UCAF-detail-screen.dart b/lib/screens/patients/profile/UCAF/UCAF-detail-screen.dart index 0a655231..83f2d68b 100644 --- a/lib/screens/patients/profile/UCAF/UCAF-detail-screen.dart +++ b/lib/screens/patients/profile/UCAF/UCAF-detail-screen.dart @@ -72,11 +72,11 @@ class _UcafDetailScreenState extends State { ), Container( margin: - EdgeInsets.symmetric(vertical: 16, horizontal: 16), + EdgeInsets.symmetric(vertical: 8, horizontal: 16), child: BorderedButton( TranslationBase.of(context).save, hasBorder: true, - vPadding: 16, + vPadding: 8, hPadding: 8, borderColor: HexColor("#B8382B"), backgroundColor: HexColor("#B8382B"), @@ -87,11 +87,11 @@ class _UcafDetailScreenState extends State { ), Container( margin: - EdgeInsets.only(left: 16, right: 16, top: 0, bottom: 16), + EdgeInsets.only(left: 16, right: 16, top: 0.0, bottom: 8), child: BorderedButton( TranslationBase.of(context).cancel, hasBorder: true, - vPadding: 16, + vPadding: 8, hPadding: 8, borderColor: Colors.white, backgroundColor: Colors.white, diff --git a/lib/screens/patients/profile/referral/my-referral-detail-screen.dart b/lib/screens/patients/profile/referral/my-referral-detail-screen.dart index 1019ede4..9a59747e 100644 --- a/lib/screens/patients/profile/referral/my-referral-detail-screen.dart +++ b/lib/screens/patients/profile/referral/my-referral-detail-screen.dart @@ -12,6 +12,7 @@ import 'package:doctor_app_flutter/widgets/shared/app_scaffold_widget.dart'; import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; import 'package:doctor_app_flutter/widgets/shared/borderedButton.dart'; import 'package:flutter/material.dart'; +import 'package:hexcolor/hexcolor.dart'; import 'package:provider/provider.dart'; import '../../../../routes.dart'; @@ -39,7 +40,7 @@ class MyReferralDetailScreen extends StatelessWidget { builder: (_, model, w) => AppScaffold( baseViewModel: model, appBarTitle: TranslationBase.of(context).referPatient, - body: Column( + body: model.patientArrivalList != null ? Column( children: [ Expanded( child: SingleChildScrollView( @@ -110,8 +111,8 @@ class MyReferralDetailScreen extends StatelessWidget { icon: 'lab.png'), PatientProfileButton( key: key, - // patient: patient, - route: PATIENT_VITAL_SIGN, + patient: model.patientArrivalList[0], + route: VITAL_SIGN_DETAILS /*PATIENT_VITAL_SIGN*/, nameLine1: TranslationBase.of(context).vital, nameLine2: TranslationBase.of(context).signs, icon: 'heartbeat.png'), @@ -160,6 +161,15 @@ class MyReferralDetailScreen extends StatelessWidget { ), ), ], + ) : Container( + child: Center( + child: AppText( + TranslationBase.of(context).patientNoDetailErrMsg, + color: HexColor("#B8382B"), + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), ), ), ); diff --git a/lib/screens/patients/profile/referral/refer-patient-screen.dart b/lib/screens/patients/profile/referral/refer-patient-screen.dart index e46ab6d5..2c5311cc 100644 --- a/lib/screens/patients/profile/referral/refer-patient-screen.dart +++ b/lib/screens/patients/profile/referral/refer-patient-screen.dart @@ -8,6 +8,7 @@ import 'package:doctor_app_flutter/screens/base/base_view.dart'; import 'package:doctor_app_flutter/util/date-utils.dart'; import 'package:doctor_app_flutter/util/dr_app_toast_msg.dart'; import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; +import 'package:doctor_app_flutter/widgets/patients/patient-referral-item-widget.dart'; import 'package:doctor_app_flutter/widgets/patients/profile/patient-page-header-widget.dart'; import 'package:doctor_app_flutter/widgets/shared/app_buttons_widget.dart'; import 'package:doctor_app_flutter/widgets/shared/app_loader_widget.dart'; @@ -40,11 +41,7 @@ class _PatientMakeReferralScreenState extends State { @override void initState() { super.initState(); - referToList = List(); - dynamic sameBranch = {"id": 1, "name": "Same Branch"}; - dynamic otherBranch = {"id": 2, "name": "Other Branch"}; - referToList.add(sameBranch); - referToList.add(otherBranch); + appointmentDate = DateTime.now(); } @@ -53,11 +50,22 @@ class _PatientMakeReferralScreenState extends State { final routeArgs = ModalRoute.of(context).settings.arguments as Map; patient = routeArgs['patient']; + referToList = List(); + dynamic sameBranch = { + "id": 1, + "name": TranslationBase.of(context).sameBranch + }; + dynamic otherBranch = { + "id": 2, + "name": TranslationBase.of(context).otherBranch + }; + referToList.add(sameBranch); + referToList.add(otherBranch); + final screenSize = MediaQuery.of(context).size; return BaseView( - onModelReady: (model) => - model.getMasterLookup(MasterKeysService.physiotherapyGoals), + onModelReady: (model) => model.getPatientReferral(patient), builder: (_, model, w) => AppScaffold( baseViewModel: model, appBarTitle: TranslationBase.of(context).referPatient, @@ -84,279 +92,50 @@ class _PatientMakeReferralScreenState extends State { indent: 0, endIndent: 0, ), - Container( - margin: - EdgeInsets.symmetric(vertical: 16, horizontal: 16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - height: 16, - ), - AppText( - TranslationBase.of(context).referPatient, - fontWeight: FontWeight.bold, - fontSize: 16, - ), - SizedBox( - height: 16, - ), - Container( - height: screenSize.height * 0.070, - child: InkWell( - onTap: referToList != null - ? () { - ListSelectDialog dialog = - ListSelectDialog( - list: referToList, - attributeName: 'name', - attributeValueId: 'id', - okText: TranslationBase.of(context).ok, - okFunction: (selectedValue) { - setState(() { - _referTo = selectedValue; - _selectedBranch = null; - _selectedClinic = null; - _selectedDoctor = null; - model - .getDoctorBranch() - .then((value) { - _selectedBranch = value; - if (_referTo['id'] == 1) { - model.getClinics( - _selectedBranch['ID']); - } - }); - }); - }, - ); - showDialog( - barrierDismissible: false, - context: context, - builder: (BuildContext context) { - return dialog; - }, - ); - } - : null, - child: TextField( - decoration: textFieldSelectorDecoration( - TranslationBase.of(context).referTo, - _referTo != null ? _referTo['name'] : null, - true), - enabled: false, - ), - ), - ), - SizedBox( - height: 10, - ), - Container( - height: screenSize.height * 0.070, - child: InkWell( - onTap: model.branchesList != null && - model.branchesList.length > 0 && - _referTo != null && - _referTo['id'] == 2 - ? () { - ListSelectDialog dialog = - ListSelectDialog( - list: model.branchesList, - attributeName: 'Desciption', - attributeValueId: 'ID', - okText: TranslationBase.of(context).ok, - okFunction: (selectedValue) { - setState(() { - _selectedBranch = selectedValue; - _selectedClinic = null; - _selectedDoctor = null; - model.getClinics( - _selectedBranch['ID']); - }); - }, - ); - showDialog( - barrierDismissible: false, - context: context, - builder: (BuildContext context) { - return dialog; - }, - ); - } - : null, - child: TextField( - decoration: textFieldSelectorDecoration( - TranslationBase.of(context).branch, - _selectedBranch != null - ? _selectedBranch['Desciption'] - : null, - true), - enabled: false, - ), - ), - ), - SizedBox( - height: 10, - ), - Container( - height: screenSize.height * 0.070, - child: InkWell( - onTap: _selectedBranch != null && - model.clinicsList != null && - model.clinicsList.length > 0 - ? () { - ListSelectDialog dialog = - ListSelectDialog( - list: model.clinicsList, - attributeName: 'ClinicDescription', - attributeValueId: 'ClinicID', - okText: TranslationBase.of(context).ok, - okFunction: (selectedValue) { - setState(() { - _selectedDoctor = null; - _selectedClinic = selectedValue; - model.getClinicDoctors( - _selectedClinic['ClinicID'] - .toString()); - }); - }, - ); - showDialog( - barrierDismissible: false, - context: context, - builder: (BuildContext context) { - return dialog; - }, - ); - } - : null, - child: TextField( - decoration: textFieldSelectorDecoration( - TranslationBase.of(context).clinic, - _selectedClinic != null - ? _selectedClinic['ClinicDescription'] - : null, - true), - enabled: false, - ), - ), - ), - SizedBox( - height: 10, - ), - Container( - height: screenSize.height * 0.070, - child: InkWell( - onTap: _selectedClinic != null && - model.doctorsList != null && - model.doctorsList.length > 0 - ? () { - ListSelectDialog dialog = - ListSelectDialog( - list: model.doctorsList, - attributeName: 'DoctorName', - attributeValueId: 'DoctorID', - okText: TranslationBase.of(context).ok, - okFunction: (selectedValue) { - setState(() { - _selectedDoctor = selectedValue; - }); - }, - ); - showDialog( - barrierDismissible: false, - context: context, - builder: (BuildContext context) { - return dialog; - }, - ); - } - : null, - child: TextField( - decoration: textFieldSelectorDecoration( - TranslationBase.of(context).doctor, - _selectedDoctor != null - ? _selectedDoctor['DoctorName'] - : null, - true), - enabled: false, - ), - ), - ), - SizedBox( - height: 10, - ), - Container( - height: screenSize.height * 0.070, - child: InkWell( - onTap: () => _selectDate(context, model), - child: TextField( - decoration: textFieldSelectorDecoration( - TranslationBase.of(context) - .chooseAppointment, - appointmentDate != null - ? "${DateUtils.convertDateToFormat(appointmentDate, "yyyy-MM-dd")}" - : null, - true, - suffixIcon: Icon( - Icons.calendar_today, - color: Colors.black, - )), - enabled: false, - ), - ), - ), - SizedBox( - height: 10, - ), - Container( - child: TextField( - decoration: textFieldSelectorDecoration( - TranslationBase.of(context).remarks, - null, - false), - enabled: true, - controller: _remarksController, - inputFormatters: [ - FilteringTextInputFormatter.allow( - RegExp(ONLY_LETTERS)) - ], - keyboardType: TextInputType.text, - minLines: 4, - maxLines: 6, - )), - ], - ), + model.patientReferral.length == 0 + ? ReferralForm(model, screenSize) + : PatientReferralItemWidget( + patientName: model.patientReferral[0].patientName, + referralStatus: "${model.patientReferral[0].referralStatus}", + isReferredTo: true, + isSameBranch: model.patientReferral[0] + .isReferralDoctorSameBranch, + referralDoctorName: + model.patientReferral[0].referredByDoctorInfo, + clinicDescription: null, + remark: + model.patientReferral[0].remarksFromSource ), ], ), - Container( - margin: EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: AppButton( - title: TranslationBase.of(context).refer, - color: HexColor("#B8382B"), - onPressed: () { - if (appointmentDate == null || - _selectedBranch == null || - _selectedClinic == null || - _selectedDoctor == null || - _remarksController.text == null) return; - model - .makeReferral( - patient, - appointmentDate.toIso8601String(), - _selectedBranch['ID'], - _selectedClinic['ClinicID'], - _selectedDoctor['DoctorID'], - _remarksController.text) - .then((_) { - DrAppToastMsg.showSuccesToast( - TranslationBase.of(context).referralSuccessMsg); - Navigator.pop(context); - }); - }, - ), - ) + if (model.patientReferral.length == 0) + Container( + margin: EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: AppButton( + title: TranslationBase.of(context).refer, + color: HexColor("#B8382B"), + onPressed: () { + if (appointmentDate == null || + _selectedBranch == null || + _selectedClinic == null || + _selectedDoctor == null || + _remarksController.text == null) return; + model + .makeReferral( + patient, + appointmentDate.toIso8601String(), + _selectedBranch['ID'], + _selectedClinic['ClinicID'], + _selectedDoctor['DoctorID'], + _remarksController.text) + .then((_) { + DrAppToastMsg.showSuccesToast( + TranslationBase.of(context).referralSuccessMsg); + Navigator.pop(context); + }); + }, + ), + ) ], ), ), @@ -365,6 +144,239 @@ class _PatientMakeReferralScreenState extends State { ); } + Widget ReferralForm(PatientReferralViewModel model, Size screenSize) { + return Container( + margin: EdgeInsets.symmetric(vertical: 16, horizontal: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + height: 16, + ), + AppText( + TranslationBase.of(context).referPatient, + fontWeight: FontWeight.bold, + fontSize: 16, + ), + SizedBox( + height: 16, + ), + Container( + height: screenSize.height * 0.070, + child: InkWell( + onTap: referToList != null + ? () { + ListSelectDialog dialog = ListSelectDialog( + list: referToList, + attributeName: 'name', + attributeValueId: 'id', + okText: TranslationBase.of(context).ok, + okFunction: (selectedValue) { + setState(() { + _referTo = selectedValue; + _selectedBranch = null; + _selectedClinic = null; + _selectedDoctor = null; + model.getDoctorBranch().then((value) { + _selectedBranch = value; + if (_referTo['id'] == 1) { + model.getClinics(_selectedBranch['ID']); + } + }); + }); + }, + ); + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) { + return dialog; + }, + ); + } + : null, + child: TextField( + decoration: textFieldSelectorDecoration( + TranslationBase.of(context).referTo, + _referTo != null ? _referTo['name'] : null, + true), + enabled: false, + ), + ), + ), + SizedBox( + height: 10, + ), + Container( + height: screenSize.height * 0.070, + child: InkWell( + onTap: model.branchesList != null && + model.branchesList.length > 0 && + _referTo != null && + _referTo['id'] == 2 + ? () { + ListSelectDialog dialog = ListSelectDialog( + list: model.branchesList, + attributeName: 'Desciption', + attributeValueId: 'ID', + okText: TranslationBase.of(context).ok, + okFunction: (selectedValue) { + setState(() { + _selectedBranch = selectedValue; + _selectedClinic = null; + _selectedDoctor = null; + model.getClinics(_selectedBranch['ID']); + }); + }, + ); + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) { + return dialog; + }, + ); + } + : null, + child: TextField( + decoration: textFieldSelectorDecoration( + TranslationBase.of(context).branch, + _selectedBranch != null + ? _selectedBranch['Desciption'] + : null, + true), + enabled: false, + ), + ), + ), + SizedBox( + height: 10, + ), + Container( + height: screenSize.height * 0.070, + child: InkWell( + onTap: _selectedBranch != null && + model.clinicsList != null && + model.clinicsList.length > 0 + ? () { + ListSelectDialog dialog = ListSelectDialog( + list: model.clinicsList, + attributeName: 'ClinicDescription', + attributeValueId: 'ClinicID', + okText: TranslationBase.of(context).ok, + okFunction: (selectedValue) { + setState(() { + _selectedDoctor = null; + _selectedClinic = selectedValue; + model.getClinicDoctors( + _selectedClinic['ClinicID'].toString()); + }); + }, + ); + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) { + return dialog; + }, + ); + } + : null, + child: TextField( + decoration: textFieldSelectorDecoration( + TranslationBase.of(context).clinic, + _selectedClinic != null + ? _selectedClinic['ClinicDescription'] + : null, + true), + enabled: false, + ), + ), + ), + SizedBox( + height: 10, + ), + Container( + height: screenSize.height * 0.070, + child: InkWell( + onTap: _selectedClinic != null && + model.doctorsList != null && + model.doctorsList.length > 0 + ? () { + ListSelectDialog dialog = ListSelectDialog( + list: model.doctorsList, + attributeName: 'DoctorName', + attributeValueId: 'DoctorID', + okText: TranslationBase.of(context).ok, + okFunction: (selectedValue) { + setState(() { + _selectedDoctor = selectedValue; + }); + }, + ); + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) { + return dialog; + }, + ); + } + : null, + child: TextField( + decoration: textFieldSelectorDecoration( + TranslationBase.of(context).doctor, + _selectedDoctor != null + ? _selectedDoctor['DoctorName'] + : null, + true), + enabled: false, + ), + ), + ), + SizedBox( + height: 10, + ), + Container( + height: screenSize.height * 0.070, + child: InkWell( + onTap: () => _selectDate(context, model), + child: TextField( + decoration: textFieldSelectorDecoration( + TranslationBase.of(context).chooseAppointment, + appointmentDate != null + ? "${DateUtils.convertDateToFormat(appointmentDate, "yyyy-MM-dd")}" + : null, + true, + suffixIcon: Icon( + Icons.calendar_today, + color: Colors.black, + )), + enabled: false, + ), + ), + ), + SizedBox( + height: 10, + ), + Container( + child: TextField( + decoration: textFieldSelectorDecoration( + TranslationBase.of(context).remarks, null, false), + enabled: true, + controller: _remarksController, + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(ONLY_LETTERS)) + ], + keyboardType: TextInputType.text, + minLines: 4, + maxLines: 6, + )), + ], + ), + ); + } + _selectDate(BuildContext context, PatientReferralViewModel model) async { // https://medium.com/flutter-community/a-deep-dive-into-datepicker-in-flutter-37e84f7d8d6c good reference // https://stackoverflow.com/a/63147062/6246772 to customize a date picker diff --git a/lib/screens/patients/profile/vital_sign/LineChartCurved.dart b/lib/screens/patients/profile/vital_sign/LineChartCurved.dart new file mode 100644 index 00000000..2f0eafcb --- /dev/null +++ b/lib/screens/patients/profile/vital_sign/LineChartCurved.dart @@ -0,0 +1,217 @@ +import 'package:doctor_app_flutter/widgets/charts/app_time_series_chart.dart'; +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; + +class LineChartCurved extends StatelessWidget { + final String title; + final List timeSeries; + final int indexes; + + LineChartCurved({this.title, this.timeSeries, this.indexes}); + + List xAxixs = List(); + List yAxixs = List(); + + @override + Widget build(BuildContext context) { + getXaxix(); + getYaxix(); + return AspectRatio( + aspectRatio: 1.1, + child: Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(18)), + // color: Colors.white, + ), + child: Stack( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox( + height: 4, + ), + Text( + title, + style: TextStyle( + color: Colors.black, + fontSize: 15, + letterSpacing: 2), + textAlign: TextAlign.center, + ), + SizedBox(height: 10,), + Expanded( + child: Padding( + padding: const EdgeInsets.only(right: 18.0, left: 16.0), + child: LineChart( + sampleData1(context), + swapAnimationDuration: const Duration(milliseconds: 250), + ), + ), + ), + const SizedBox( + height: 10, + ), + ], + ), + ], + ), + ), + ); + } + + getXaxix() { + for (int index = 0; index < timeSeries.length; index++) { + int mIndex = indexes * index; + if (mIndex < timeSeries.length) { + xAxixs.add(mIndex); + } + } + } + getYaxix() { + int indexess= (timeSeries.length*0.30).toInt(); + for (int index = 0; index < timeSeries.length; index++) { + int mIndex = indexess * index; + if (mIndex < timeSeries.length) { + yAxixs.add(timeSeries[mIndex].sales); + } + } + } + + LineChartData sampleData1(context) { + return LineChartData( + lineTouchData: LineTouchData( + touchTooltipData: LineTouchTooltipData( + tooltipBgColor: Colors.white, + + ), + touchCallback: (LineTouchResponse touchResponse) {}, + handleBuiltInTouches: true, + ), + gridData: FlGridData( + show: true, drawVerticalLine: true, drawHorizontalLine: true), + titlesData: FlTitlesData( + bottomTitles: SideTitles( + showTitles: true, + getTextStyles: (value) => const TextStyle( + color: Colors.black, + fontSize: 10, + ), + rotateAngle:-65, + //rotateAngle:-65, + margin: 22, + getTitles: (value) { + if (timeSeries.length < 15) { + if (timeSeries.length > value.toInt()) { + return '${timeSeries[value.toInt()].time.month}/ ${timeSeries[value.toInt()].time.year}'; + } else + return ''; + } else { + if (value.toInt() == 0) + return '${timeSeries[value.toInt()].time.month}/ ${timeSeries[value.toInt()].time.year}'; + if (value.toInt() == timeSeries.length - 1) + return '${timeSeries[value.toInt()].time.month}/ ${timeSeries[value.toInt()].time.year}'; + if (xAxixs.contains(value.toInt())) { + return '${timeSeries[value.toInt()].time.month}/ ${timeSeries[value.toInt()].time.year}'; + } + } + return ''; + }, + ), + leftTitles: SideTitles( + showTitles: true, + getTextStyles: (value) => const TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold, + fontSize: 10, + ), + getTitles: (value) { + // if (timeSeries.length < 10) { + // return '${value.toInt()}'; + // } else { + // if (value == getMinY()) + // return '${value.toInt()}'; + // if (value == getMaxY()) + // return '${value.toInt()}'; + // if (yAxixs.contains(value)) { + // return '${value.toInt()}'; + // } + // return ''; + // } + return '${value.toInt()}'; + }, + margin: 12, + ), + ), + borderData: FlBorderData( + show: true, + border: const Border( + bottom: BorderSide( + color: Colors.black, + width: 0.5, + ), + left: BorderSide( + color: Colors.black, + ), + right: BorderSide( + color: Colors.black, + ), + top: BorderSide( + color: Colors.transparent, + ), + ), + ), + minX: 0, + maxX: (timeSeries.length - 1).toDouble(), + maxY: getMaxY()+0.3, + minY: getMinY(), + lineBarsData: getData(context), + ); + } + + double getMaxY() { + double max = 0; + timeSeries.forEach((element) { + double resultValueDouble = element.sales; + if (resultValueDouble > max) max = resultValueDouble; + }); + + return max.roundToDouble() ; + } + + double getMinY() { + double min = timeSeries[0].sales; + timeSeries.forEach((element) { + double resultValueDouble = element.sales; + if (resultValueDouble < min) min = resultValueDouble; + }); + int value = min.toInt(); + + return value.toDouble(); + } + + List getData(context) { + List spots = List(); + for (int index = 0; index < timeSeries.length; index++) { + spots.add(FlSpot(index.toDouble(), timeSeries[index].sales)); + } + + final LineChartBarData lineChartBarData1 = LineChartBarData( + spots: spots, + isCurved: true, + colors: [Theme.of(context).primaryColor], + barWidth: 5, + isStrokeCapRound: true, + dotData: FlDotData( + show: false, + ), + belowBarData: BarAreaData( + show: false, + ), + ); + + return [ + lineChartBarData1, + ]; + } +} diff --git a/lib/screens/patients/profile/vital_sign/LineChartCurvedBloodPressure.dart b/lib/screens/patients/profile/vital_sign/LineChartCurvedBloodPressure.dart new file mode 100644 index 00000000..e816c145 --- /dev/null +++ b/lib/screens/patients/profile/vital_sign/LineChartCurvedBloodPressure.dart @@ -0,0 +1,257 @@ +import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; +import 'package:doctor_app_flutter/widgets/charts/app_time_series_chart.dart'; +import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; + +class LineChartCurvedBloodPressure extends StatelessWidget { + final String title; + final List timeSeries1; + final List timeSeries2; + final int indexes; + + LineChartCurvedBloodPressure( + {this.title, this.timeSeries1, this.indexes, this.timeSeries2}); + + List xAxixs = List(); + List yAxixs = List(); + + @override + Widget build(BuildContext context) { + getXaxix(); + return AspectRatio( + aspectRatio: 1.1, + child: Container( + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(18)), + // color: Colors.white, + ), + child: Stack( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox( + height: 15, + ), + Text( + title, + style: TextStyle( + color: Colors.black, fontSize: 15, letterSpacing: 2), + textAlign: TextAlign.center, + ), + SizedBox( + height: 10, + ), + Expanded( + child: Padding( + padding: + const EdgeInsets.only(right: 18.0, left: 16.0, top: 15), + child: LineChart( + sampleData1(context), + swapAnimationDuration: const Duration(milliseconds: 250), + ), + ), + ), + SizedBox( + height: 10, + ), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + children: [ + Container( + width: 20, + height: 20, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: Theme.of(context).primaryColor), + ), + SizedBox(width: 5,), + AppText(TranslationBase.of(context).systolicLng) + ], + ), + SizedBox(width: 15,), + Row( + children: [ + Container( + width: 20, + height: 20, + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: Colors.grey), + ), + SizedBox(width: 5,), + AppText(TranslationBase.of(context).diastolicLng) + ], + ), + ], + ) + ], + ), + ], + ), + ), + ); + } + + getXaxix() { + for (int index = 0; index < timeSeries1.length; index++) { + int mIndex = indexes * index; + if (mIndex < timeSeries1.length) { + xAxixs.add(mIndex); + } + } + } + + LineChartData sampleData1(context) { + return LineChartData( + lineTouchData: LineTouchData( + touchTooltipData: LineTouchTooltipData( + tooltipBgColor: Colors.white, + ), + touchCallback: (LineTouchResponse touchResponse) {}, + handleBuiltInTouches: true, + ), + gridData: FlGridData( + show: true, drawVerticalLine: true, drawHorizontalLine: true), + titlesData: FlTitlesData( + bottomTitles: SideTitles( + showTitles: true, + getTextStyles: (value) => const TextStyle( + color: Colors.black, + fontSize: 10, + ), + rotateAngle: -65, + //rotateAngle:-65, + margin: 22, + getTitles: (value) { + if (timeSeries1.length < 15) { + if (timeSeries1.length > value.toInt()) { + return '${timeSeries1[value.toInt()].time.month}/ ${timeSeries1[value.toInt()].time.year}'; + } else + return ''; + } else { + if (value.toInt() == 0) + return '${timeSeries1[value.toInt()].time.month}/ ${timeSeries1[value.toInt()].time.year}'; + if (value.toInt() == timeSeries1.length - 1) + return '${timeSeries1[value.toInt()].time.month}/ ${timeSeries1[value.toInt()].time.year}'; + if (xAxixs.contains(value.toInt())) { + return '${timeSeries1[value.toInt()].time.month}/ ${timeSeries1[value.toInt()].time.year}'; + } + } + return ''; + }, + ), + leftTitles: SideTitles( + showTitles: true, + getTextStyles: (value) => const TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold, + fontSize: 10, + ), + getTitles: (value) { + return '${value.toInt()}'; + }, + margin: 12, + ), + ), + borderData: FlBorderData( + show: true, + border: const Border( + bottom: BorderSide( + color: Colors.black, + width: 0.5, + ), + left: BorderSide( + color: Colors.black, + ), + right: BorderSide( + color: Colors.black, + ), + top: BorderSide( + color: Colors.transparent, + ), + ), + ), + minX: 0, + maxX: (timeSeries1.length - 1).toDouble(), + maxY: getMaxY() + 0.3, + minY: getMinY(), + lineBarsData: getData(context), + ); + } + + double getMaxY() { + double max = 0; + timeSeries1.forEach((element) { + double resultValueDouble = element.sales; + if (resultValueDouble > max) max = resultValueDouble; + }); + timeSeries2.forEach((element) { + double resultValueDouble = element.sales; + if (resultValueDouble > max) max = resultValueDouble; + }); + + return max.roundToDouble(); + } + + double getMinY() { + double min = timeSeries1[0].sales; + timeSeries1.forEach((element) { + double resultValueDouble = element.sales; + if (resultValueDouble < min) min = resultValueDouble; + }); + timeSeries2.forEach((element) { + double resultValueDouble = element.sales; + if (resultValueDouble < min) min = resultValueDouble; + }); + + int value = min.toInt(); + + return value.toDouble(); + } + + List getData(context) { + List spots = List(); + for (int index = 0; index < timeSeries1.length; index++) { + spots.add(FlSpot(index.toDouble(), timeSeries1[index].sales)); + } + + List spots2 = List(); + for (int index = 0; index < timeSeries2.length; index++) { + spots2.add(FlSpot(index.toDouble(), timeSeries2[index].sales)); + } + + final LineChartBarData lineChartBarData1 = LineChartBarData( + spots: spots, + isCurved: true, + colors: [Theme.of(context).primaryColor], + barWidth: 5, + isStrokeCapRound: true, + dotData: FlDotData( + show: false, + ), + belowBarData: BarAreaData( + show: false, + ), + ); + final LineChartBarData lineChartBarData2 = LineChartBarData( + spots: spots2, + isCurved: true, + colors: [Colors.grey], + barWidth: 5, + isStrokeCapRound: true, + dotData: FlDotData( + show: false, + ), + belowBarData: BarAreaData( + show: false, + ), + ); + + return [lineChartBarData1, lineChartBarData2]; + } +} diff --git a/lib/screens/patients/profile/vital_sign/vital-signs-screen.dart b/lib/screens/patients/profile/vital_sign/vital-signs-screen.dart index a53a3619..6b2543be 100644 --- a/lib/screens/patients/profile/vital_sign/vital-signs-screen.dart +++ b/lib/screens/patients/profile/vital_sign/vital-signs-screen.dart @@ -18,6 +18,8 @@ class PatientVitalSignScreen extends StatelessWidget { Widget build(BuildContext context) { final routeArgs = ModalRoute.of(context).settings.arguments as Map; PatiantInformtion patient = routeArgs['patient']; + String from = routeArgs['from']; + String to = routeArgs['to']; return BaseView( onModelReady: (model) => model.getPatientVitalSign(patient), @@ -115,7 +117,7 @@ class PatientVitalSignScreen extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Row( + /*Row( children: [ AppText( "${TranslationBase.of(context).waistSize} :", @@ -133,7 +135,7 @@ class PatientVitalSignScreen extends StatelessWidget { fontWeight: FontWeight.normal, ), ], - ), + ),*/ Row( children: [ AppText( diff --git a/lib/screens/patients/profile/vital_sign/vital_sign_details_blood_pressurewideget.dart b/lib/screens/patients/profile/vital_sign/vital_sign_details_blood_pressurewideget.dart new file mode 100644 index 00000000..df7b80d6 --- /dev/null +++ b/lib/screens/patients/profile/vital_sign/vital_sign_details_blood_pressurewideget.dart @@ -0,0 +1,146 @@ +import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; +import 'package:doctor_app_flutter/models/patient/vital_sign/patient-vital-sign-data.dart'; +import 'package:doctor_app_flutter/models/patient/vital_sign/patient-vital-sign-history.dart'; +import 'package:doctor_app_flutter/util/date-utils.dart'; +import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; +import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class VitalSignBloodPressureWidget extends StatefulWidget { + final List vitalList; + final String title1; + final String title2; + final String title3; + final String viewKey1; + final String viewKey2; + + VitalSignBloodPressureWidget( + {Key key, this.vitalList, this.title1, this.title2, this.viewKey1, this.title3, this.viewKey2}); + + @override + _VitalSignDetailsWidgetState createState() => _VitalSignDetailsWidgetState(); +} + +class _VitalSignDetailsWidgetState extends State { + @override + Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); + return Container( + decoration: BoxDecoration( + color: Colors.transparent, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10.0), topRight: Radius.circular(10.0)), + border: Border.all(color: Colors.grey, width: 1), + ), + margin: EdgeInsets.all(20), + child: Container( + color: Colors.transparent, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Table( + border: TableBorder.symmetric( + inside: BorderSide(width: 2.0, color: Colors.grey[300]), + ), + children: fullData(projectViewModel), + ), + ], + ), + ), + ); + } + + List fullData(ProjectViewModel projectViewModel) { + List tableRow = []; + tableRow.add(TableRow(children: [ + Container( + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).primaryColor, + borderRadius: BorderRadius.only( + topLeft:projectViewModel.isArabic? Radius.circular(0.0):Radius.circular(10.0), + topRight: projectViewModel.isArabic? Radius.circular(10.0):Radius.circular(0.0) + ), + ), + child: Center( + child: AppText( + TranslationBase.of(context).date, + color: Colors.white, + ), + ), + height: 60, + ), + ), + Container( + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).primaryColor, + + ), + child: Center( + child: AppText(widget.title2, color: Colors.white), + ), + height: 60), + ), + Container( + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).primaryColor, + borderRadius: BorderRadius.only( + topRight: projectViewModel.isArabic? Radius.circular(0.0):Radius.circular(10.0), + topLeft: projectViewModel.isArabic? Radius.circular(10.0):Radius.circular(0.0) + ), + ), + child: Center( + child: AppText(widget.title3, color: Colors.white), + ), + height: 60), + ), + ])); + widget.vitalList.forEach((vital) { + var data = vital.toJson()[widget.viewKey1]; + if (data != 0) + tableRow.add(TableRow(children: [ + Container( + child: Container( + padding: EdgeInsets.all(10), + color: Colors.white, + child: Center( + child: AppText( + '${projectViewModel.isArabic ? DateUtils.getWeekDayArabic(vital.vitalSignDate.weekday) : DateUtils.getWeekDay(vital.vitalSignDate.weekday)}, ${vital.vitalSignDate.day} ${projectViewModel.isArabic ? DateUtils.getMonthArabic(vital.vitalSignDate.month) : DateUtils.getMonth(vital.vitalSignDate.month)}, ${vital.vitalSignDate.year} ', + textAlign: TextAlign.center, + ), + ), + ), + ), + Container( + child: Container( + padding: EdgeInsets.all(10), + color: Colors.white, + child: Center( + child: AppText( + '${vital.toJson()[widget.viewKey1]}', + textAlign: TextAlign.center, + ), + ), + ), + ), + Container( + child: Container( + padding: EdgeInsets.all(10), + color: Colors.white, + child: Center( + child: AppText( + '${vital.toJson()[widget.viewKey2]}', + textAlign: TextAlign.center, + ), + ), + ), + ), + ])); + }); + return tableRow; + } +} diff --git a/lib/screens/patients/profile/vital_sign/vital_sign_details_screen.dart b/lib/screens/patients/profile/vital_sign/vital_sign_details_screen.dart index cf8ee839..ad312625 100644 --- a/lib/screens/patients/profile/vital_sign/vital_sign_details_screen.dart +++ b/lib/screens/patients/profile/vital_sign/vital_sign_details_screen.dart @@ -1,246 +1,197 @@ -import 'package:doctor_app_flutter/core/viewModel/patient_view_model.dart'; -import 'package:doctor_app_flutter/models/patient/vital_sign/vital_sign_req_model.dart'; +import 'package:doctor_app_flutter/core/viewModel/patient-vital-sign-viewmodel.dart'; +import 'package:doctor_app_flutter/lookups/patient_lookup.dart'; +import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart'; import 'package:doctor_app_flutter/screens/base/base_view.dart'; +import 'package:doctor_app_flutter/screens/patients/profile/vital_sign/vital_sign_item.dart'; +import 'package:doctor_app_flutter/screens/patients/profile/vital_sign/vital_sign_item_details_screen.dart'; import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; -import 'package:doctor_app_flutter/widgets/shared/errors/dr_app_embedded_error.dart'; +import 'package:doctor_app_flutter/widgets/shared/app_scaffold_widget.dart'; +import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; +import 'package:doctor_app_flutter/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; -import '../../../../config/shared_pref_kay.dart'; -import '../../../../config/size_config.dart'; -import '../../../../lookups/patient_lookup.dart'; -import '../../../../models/patient/patiant_info_model.dart'; -import '../../../../models/patient/vital_sign/vital_sign_res_model.dart'; -import '../../../../routes.dart'; -import '../../../../screens/patients/profile/vital_sign/vital_sign_item.dart'; -import '../../../../util/dr_app_shared_pref.dart'; -import '../../../../widgets/shared/app_scaffold_widget.dart'; +class VitalSignDetailsScreen extends StatelessWidget { -DrAppSharedPreferances sharedPref = new DrAppSharedPreferances(); + int appointmentNo; + int projectID; + bool isNotOneAppointment; + VitalSignDetailsScreen({this.appointmentNo, this.projectID,this.isNotOneAppointment=true}); -class VitalSignDetailsScreen extends StatefulWidget { - // VitalSignDetailsScreen({Key key, this.vitalSing}) : super(key: key); @override - _VitalSignDetailsScreenState createState() => _VitalSignDetailsScreenState(); -} - -class _VitalSignDetailsScreenState extends State { - VitalSignResModel vitalSing; - String url = "assets/images/"; - - - /* - *@author: Elham Rababah - *@Date:28/4/2020 - *@param: context - *@return: - *@desc: getVitalSignList Function - */ - getVitalSignList(BuildContext context, PatientViewModel model) async { + Widget build(BuildContext context) { final routeArgs = ModalRoute.of(context).settings.arguments as Map; PatiantInformtion patient = routeArgs['patient']; - String token = await sharedPref.getString(TOKEN); - String type = await sharedPref.getString(SLECTED_PATIENT_TYPE); - int inOutpatientType = 1; - if (type == '0') { - inOutpatientType = 2; - } - print(type); - VitalSignReqModel vitalSignReqModel = VitalSignReqModel( - patientID: patient.patientId, - projectID: patient.projectId, - tokenID: token, - patientTypeID: patient.patientType, - inOutpatientType: inOutpatientType, - languageID: 2, - transNo: - patient.admissionNo != null ? int.parse(patient.admissionNo) : 0); - model.getPatientVitalSign(vitalSignReqModel.toJson()); - } - - - - final double contWidth = SizeConfig.realScreenWidth * 0.70; + String from = routeArgs['from']; + String to = routeArgs['to']; + String imageBasePath = 'assets/images/'; - @override - Widget build(BuildContext context) { - final routeArgs = ModalRoute.of(context).settings.arguments as Map; - vitalSing = routeArgs['vitalSing']; - return BaseView( - onModelReady: (model) => getVitalSignList(context, model), - builder: (_, model, w) => AppScaffold( - baseViewModel: model, + return BaseView( + onModelReady: (model) => model.getPatientVitalSignHistory(patient, from, to), + builder: (_, mode, widget) => AppScaffold( + isShowAppBar: true, + baseViewModel: mode, appBarTitle: TranslationBase.of(context).vitalSign, - body: model.patientVitalSignOrderdSubList.length == 0 - ? DrAppEmbeddedError( - error: 'You don\'t have any vital Sings') - : Container( - child: Column( - children: [ - Row( - children: [ - InkWell( - onTap: () { - Navigator.of(context).pushNamed( - BODY_MEASUREMENTS, - arguments: { - 'title': TranslationBase.of(context) - .bodyMeasurements, - 'key': - vitalSignDetails.bodyMeasurements - }); - }, - child: Container( - child: VitalSignItem( - des: TranslationBase.of(context) - .bodyMeasurements, - url: url + 'heartbeat.png', - lastVal: model - .patientVitalSignOrderdSubList[0] - .heightCm - .toString(), - unit: 'Cm', - ), - ), - ), - InkWell( - onTap: () { - Navigator.of(context).pushNamed( - BODY_MEASUREMENTS, - arguments: { - 'title': TranslationBase.of(context) - .temperature, - 'key': vitalSignDetails.temperature, - }); - }, - child: Container( - child: VitalSignItem( - des: TranslationBase.of(context) - .temperature, - url: url + 'heartbeat.png', - lastVal: model - .patientVitalSignOrderdSubList[0] - .temperatureCelcius - .toString(), - unit: 'C', - ), - ), - ), - ], + body: mode.patientVitalSignsHistory.length > 0 + ? Container( + child: ListView( + children: [ + Row( + children: [ + InkWell( + onTap: () =>isNotOneAppointment? Navigator.push( + context, + FadePage( + page: VitalSignItemDetailsScreen( + pageKey: vitalSignDetails.Height, + pageTitle: TranslationBase.of(context).height, + vitalList: mode.patientVitalSignsHistory, + ), + ), + ):null, + child: Container( + child: VitalSignItem( + des: TranslationBase.of(context).height, + imagePath: "${imageBasePath}vital_height.png", + lastVal: mode.heightCm, + unit: TranslationBase.of(context).cm, + ), + ), + ), + InkWell( + onTap: () => isNotOneAppointment ? Navigator.push( + context, + FadePage( + page: VitalSignItemDetailsScreen( + pageKey: vitalSignDetails.Weight, + pageTitle: TranslationBase.of(context).weight, + vitalList: mode.patientVitalSignsHistory, + ), + ), + ):null, + child: VitalSignItem( + des: TranslationBase.of(context).weight, + imagePath: "${imageBasePath}vital_weight.png", + unit: TranslationBase.of(context).kg, + lastVal: mode.weightKg, + ), + ), + ], + ), + Row( + children: [ + InkWell( + onTap: () => isNotOneAppointment ? Navigator.push( + context, + FadePage( + page: VitalSignItemDetailsScreen( + pageKey: vitalSignDetails.BodyMeasurements, + pageTitle: TranslationBase.of(context) + .bodyMeasurements, + vitalList: mode.patientVitalSignsHistory, + ), + ), + ): null, + child: VitalSignItem( + des: TranslationBase.of(context).body, + imagePath: "${imageBasePath}vital_body_mass.png", + lastVal: mode.bodyMax, + unit: TranslationBase.of(context).mass, + ), + ), + InkWell( + onTap: () => isNotOneAppointment ? Navigator.push( + context, + FadePage( + page: VitalSignItemDetailsScreen( + pageKey: vitalSignDetails.Temperature, + pageTitle: + TranslationBase.of(context).temperature, + vitalList: mode.patientVitalSignsHistory, + ), + ), + ):null, + child: Container( + child: VitalSignItem( + des: TranslationBase.of(context).temperature, + imagePath: "${imageBasePath}vital_temperature.png", + lastVal: mode.temperatureCelcius, + unit: TranslationBase.of(context).tempC, ), - Row( - children: [ - InkWell( - onTap: () { - Navigator.of(context).pushNamed( - BODY_MEASUREMENTS, - arguments: { - 'title': - TranslationBase.of(context).pulse, - 'key': vitalSignDetails.pulse - }); - }, - child: VitalSignItem( - des: TranslationBase.of(context).pulse, - url: url + 'heartbeat.png', - lastVal: model - .patientVitalSignOrderdSubList[0] - .pulseBeatPerMinute - .toString(), - unit: 'M', - ), - ), - InkWell( - onTap: () { - Navigator.of(context).pushNamed( - BODY_MEASUREMENTS, - arguments: { - 'title': TranslationBase.of(context) - .respiration, - 'key': vitalSignDetails.pespiration - }); - }, - child: VitalSignItem( - des: - TranslationBase.of(context).respiration, - url: url + 'heartbeat.png', - lastVal: model - .patientVitalSignOrderdSubList[0] - .respirationBeatPerMinute - .toString(), - unit: 'M', - ), - ), - ], + ), + ), + ], + ), + Row( + children: [ + InkWell( + onTap: () => isNotOneAppointment ? Navigator.push( + context, + FadePage( + page: VitalSignItemDetailsScreen( + pageKey: vitalSignDetails.heart, + pageTitle: TranslationBase.of(context).heart, + vitalList: mode.patientVitalSignsHistory, + ), ), - Row( - children: [ - InkWell( - onTap: () { - Navigator.of(context).pushNamed( - BODY_MEASUREMENTS, - arguments: { - 'title': TranslationBase.of(context) - .bloodPressure, - 'key': vitalSignDetails.bloodPressure - }); - }, - child: VitalSignItem( - des: TranslationBase.of(context) - .bloodPressure, - url: url + 'heartbeat.png', - lastVal: model - .patientVitalSignOrderdSubList[0] - .bloodPressure - .toString(), - unit: '', - ), - ), - InkWell( - onTap: () { - Navigator.of(context).pushNamed( - BODY_MEASUREMENTS, - arguments: { - 'title': TranslationBase.of(context) - .oxygenation, - 'key': vitalSignDetails.oxygenation - }); - }, - child: VitalSignItem( - des: - TranslationBase.of(context).oxygenation, - url: url + 'heartbeat.png', - lastVal: model - .patientVitalSignOrderdSubList[0].fIO2 - .toString(), - unit: '', - ), - ), - ], + ):null, + child: VitalSignItem( + des: TranslationBase.of(context).heart, + imagePath: "${imageBasePath}vital_heart_rate.png", + lastVal: mode.hartRat, + unit: TranslationBase.of(context).bpm, + ), + ), + InkWell( + onTap: () => isNotOneAppointment ? Navigator.push( + context, + FadePage( + page: VitalSignItemDetailsScreen( + pageKey: vitalSignDetails.Respiration, + pageTitle: + TranslationBase.of(context).respirationRate, + vitalList: mode.patientVitalSignsHistory, + ), ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - InkWell( - onTap: () { - Navigator.of(context).pushNamed( - BODY_MEASUREMENTS, - arguments: { - 'title': TranslationBase.of(context) - .painScale, - 'key': vitalSignDetails.painScale - }); - }, - child: VitalSignItem( - des: TranslationBase - .of(context) - .painScale, - url: url + 'heartbeat.png', - ), - ), - ], + ):null, + child: VitalSignItem( + des: TranslationBase.of(context).respirationRate, + imagePath: "${imageBasePath}vital_respiration.png", + lastVal: mode.respirationBeatPerMinute, + unit: TranslationBase.of(context).respirationSigns, + ), + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + InkWell( + onTap: () => isNotOneAppointment ? Navigator.push( + context, + FadePage( + page: VitalSignItemDetailsScreen( + pageKey: vitalSignDetails.BloodPressure, + pageTitle: TranslationBase.of(context).bloodPressure, + vitalList: mode.patientVitalSignsHistory, + ), ), - ], + ):null, + child: VitalSignItem( + des: TranslationBase.of(context).bloodPressure, + imagePath: "${imageBasePath}vital_blood-pressure.png", + lastVal: mode.bloodPressure, + unit: TranslationBase.of(context).sysDias, + ), + ), + ], + ), + ], + ), + ) + : Center( + child: AppText('No Data'), ), - ),),); + ), + ); } } diff --git a/lib/screens/patients/profile/vital_sign/vital_sign_details_wideget.dart b/lib/screens/patients/profile/vital_sign/vital_sign_details_wideget.dart new file mode 100644 index 00000000..8e936f1e --- /dev/null +++ b/lib/screens/patients/profile/vital_sign/vital_sign_details_wideget.dart @@ -0,0 +1,122 @@ +import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; +import 'package:doctor_app_flutter/models/patient/vital_sign/patient-vital-sign-data.dart'; +import 'package:doctor_app_flutter/models/patient/vital_sign/patient-vital-sign-history.dart'; +import 'package:doctor_app_flutter/util/date-utils.dart'; +import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; +import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:hexcolor/hexcolor.dart'; +import 'package:provider/provider.dart'; + +class VitalSignDetailsWidget extends StatefulWidget { + final List vitalList; + final String title1; + final String title2; + final String viewKey; + + VitalSignDetailsWidget( + {Key key, this.vitalList, this.title1, this.title2, this.viewKey}); + + @override + _VitalSignDetailsWidgetState createState() => _VitalSignDetailsWidgetState(); +} + +class _VitalSignDetailsWidgetState extends State { + @override + Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); + return Container( + decoration: BoxDecoration( + color: Colors.transparent, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(10.0), topRight: Radius.circular(10.0)), + border: Border.all(color: Colors.grey, width: 1), + ), + margin: EdgeInsets.all(20), + child: Container( + color: Colors.transparent, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Table( + border: TableBorder.symmetric( + inside: BorderSide(width: 2.0, color: Colors.grey[300]), + ), + children: fullData(projectViewModel), + ), + ], + ), + ), + ); + } + + List fullData(ProjectViewModel projectViewModel) { + List tableRow = []; + tableRow.add(TableRow(children: [ + Container( + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).primaryColor, + borderRadius: BorderRadius.only( + topLeft:projectViewModel.isArabic? Radius.circular(0.0):Radius.circular(10.0), + topRight: projectViewModel.isArabic? Radius.circular(10.0):Radius.circular(0.0) + ), + ), + child: Center( + child: AppText( + TranslationBase.of(context).date, + color: Colors.white, + ), + ), + height: 60, + ), + ), + Container( + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).primaryColor, + borderRadius: BorderRadius.only( + topRight: projectViewModel.isArabic? Radius.circular(0.0):Radius.circular(10.0), + topLeft: projectViewModel.isArabic? Radius.circular(10.0):Radius.circular(0.0) + ), + ), + child: Center( + child: AppText(widget.title2, color: Colors.white), + ), + height: 60), + ) + ])); + widget.vitalList.forEach((vital) { + var data = vital.toJson()[widget.viewKey]; + if (data != 0) + tableRow.add(TableRow(children: [ + Container( + child: Container( + padding: EdgeInsets.all(10), + color: Colors.white, + child: Center( + child: AppText( + '${projectViewModel.isArabic ? DateUtils.getWeekDayArabic(vital.vitalSignDate.weekday) : DateUtils.getWeekDay(vital.vitalSignDate.weekday)}, ${vital.vitalSignDate.day} ${projectViewModel.isArabic ? DateUtils.getMonthArabic(vital.vitalSignDate.month) : DateUtils.getMonth(vital.vitalSignDate.month)}, ${vital.vitalSignDate.year} ', + textAlign: TextAlign.center, + ), + ), + ), + ), + Container( + child: Container( + padding: EdgeInsets.all(10), + color: Colors.white, + child: Center( + child: AppText( + '${vital.toJson()[widget.viewKey]}', + textAlign: TextAlign.center, + ), + ), + ), + ), + ])); + }); + return tableRow; + } +} diff --git a/lib/screens/patients/profile/vital_sign/vital_sign_item.dart b/lib/screens/patients/profile/vital_sign/vital_sign_item.dart index 1e0ce2cf..33b25e82 100644 --- a/lib/screens/patients/profile/vital_sign/vital_sign_item.dart +++ b/lib/screens/patients/profile/vital_sign/vital_sign_item.dart @@ -1,32 +1,23 @@ +import 'package:doctor_app_flutter/config/size_config.dart'; +import 'package:doctor_app_flutter/widgets/shared/rounded_container_widget.dart'; import 'package:flutter/material.dart'; import 'package:hexcolor/hexcolor.dart'; -import '../../../../config/size_config.dart'; -import '../../../../widgets/shared/rounded_container_widget.dart'; - -/* - *@author: Elham Rababah - *@Date:03/6/2020 - *@param: - *@return: - *@desc: VitalSignItem - */ class VitalSignItem extends StatelessWidget { const VitalSignItem( {Key key, - @required this.url, @required this.des, this.lastVal = 'N/A', this.unit = '', this.height, - this.width}) + this.width, + @required this.imagePath}) : super(key: key); - final String url; final String des; final String lastVal; final String unit; - + final String imagePath; final double height; final double width; @@ -34,52 +25,70 @@ class VitalSignItem extends StatelessWidget { Widget build(BuildContext context) { return RoundedContainer( margin: 0.025 * SizeConfig.realScreenWidth, - height: 0.14 * SizeConfig.realScreenHeight, + height: 0.15 * SizeConfig.realScreenHeight, width: 0.45 * SizeConfig.realScreenWidth, child: Container( padding: EdgeInsets.all(5), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - flex: 2, - child: Text( - des, - style: TextStyle( - fontSize: 1.7 * SizeConfig.textMultiplier, - color: HexColor('#B8382C'), - fontWeight: FontWeight.bold), - ), - ), - Expanded( - flex: 1, - child: Column( + Container( + height: 0.10 * SizeConfig.realScreenHeight, + child: Row( children: [ Expanded( - child: Image.asset( - url, - height: SizeConfig.heightMultiplier * 7, - ), - ), - Expanded( - child: RichText( - text: TextSpan( - style: TextStyle(color: Colors.black), - children: [ - new TextSpan(text: lastVal), - new TextSpan( - text: ' ${unit}', + flex: 2, + child: Align( + alignment: Alignment.topLeft, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + des, style: TextStyle( + fontSize: 1.7 * SizeConfig.textMultiplier, color: HexColor('#B8382C'), + fontWeight: FontWeight.bold, ), ), - ], + ), ), - )) + ), + Expanded( + flex: 1, + child: Container( + child: Image.asset( + imagePath, + width: 40, + height: 40, + )), + ) ], ), - ) + ), + Expanded( + child: Container( + width: double.infinity, + child: Align( + alignment: Alignment.topRight, + child: Container( + margin: EdgeInsets.only(left: 5, right: 5), + child: RichText( + text: TextSpan( + style: TextStyle(color: Colors.black), + children: [ + TextSpan(text: "$lastVal "), + TextSpan( + text: unit, + style: TextStyle( + color: HexColor('#B8382C'), + ), + ), + ]), + ), + ), + ), + ), + ), ], ), ), diff --git a/lib/screens/patients/profile/vital_sign/vital_sign_item_details_screen.dart b/lib/screens/patients/profile/vital_sign/vital_sign_item_details_screen.dart index 853bec15..bd828138 100644 --- a/lib/screens/patients/profile/vital_sign/vital_sign_item_details_screen.dart +++ b/lib/screens/patients/profile/vital_sign/vital_sign_item_details_screen.dart @@ -1 +1,196 @@ -import 'package:doctor_app_flutter/core/viewModel/patient_view_model.dart'; import 'package:doctor_app_flutter/screens/base/base_view.dart'; import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; import 'package:doctor_app_flutter/widgets/shared/errors/dr_app_embedded_error.dart'; import 'package:flutter/material.dart'; import '../../../../lookups/patient_lookup.dart'; import '../../../../models/patient/vital_sign/vital_sign_res_model.dart'; import '../../../../screens/patients/profile/vital_sign/vital_sing_chart_and_detials.dart'; import '../../../../widgets/shared/app_scaffold_widget.dart'; /* *@author: Elham Rababah *@Date:03/6/2020 *@param: *@return: *@desc: VitalSignItemDetailsScreen */ class VitalSignItemDetailsScreen extends StatelessWidget { VitalSignItemDetailsScreen(); List vitalList = []; String pageTitle; @override Widget build(BuildContext context) { final routeArgs = ModalRoute.of(context).settings.arguments as Map; pageTitle = routeArgs['title']; var pageKey = routeArgs['key']; List VSchart; switch (pageKey) { case vitalSignDetails.bodyMeasurements: VSchart = [ { 'name': 'Highet', 'title1': 'Date', 'title2': 'Cm', 'viewKey': 'HeightCm', }, { 'name': 'Weight Kg', 'title1': 'Date', 'title2': 'Kg', 'viewKey': 'WeightKg', }, { 'name': 'BodyMassIndex', 'title1': 'Date', 'title2': 'BodyMass', 'viewKey': 'BodyMassIndex', }, { 'name': 'HeadCircumCm', 'title1': 'Date', 'title2': 'Cm', 'viewKey': 'HeadCircumCm', }, { 'name': 'Ideal Body Weight (Lbs)', 'title1': 'Date', 'title2': 'Ideal Weight', 'viewKey': 'IdealBodyWeightLbs', }, { 'name': 'LeanBodyWeightLbs (Lbs)', 'title1': 'Date', 'title2': 'Lean Weight', 'viewKey': 'LeanBodyWeightLbs', } ]; break; case vitalSignDetails.temperature: VSchart = [ { 'name': 'Temperature In Celcius', 'title1': 'Date', 'title2': 'C', 'viewKey': 'TemperatureCelcius', }, ]; break; case vitalSignDetails.pulse: VSchart = [ { 'name': 'Pulse Beat Per Minute', 'title1': 'Date', 'title2': 'Minute', 'viewKey': 'PulseBeatPerMinute', }, ]; break; case vitalSignDetails.pespiration: VSchart = [ { 'name': 'Respiration Beat Per Minute', 'title1': 'Date', 'title2': 'Beat Per Minute', 'viewKey': 'RespirationBeatPerMinute', }, ]; break; case vitalSignDetails.bloodPressure: VSchart = [ { 'name': 'Blood Pressure Higher', 'title1': 'Date', 'title2': 'Minute', 'viewKey': 'BloodPressureHigher', }, { 'name': 'Blood Pressure Lower', 'title1': 'Date', 'title2': 'Minute', 'viewKey': 'BloodPressureLower', } ]; break; case vitalSignDetails.oxygenation: VSchart = [ { 'name': 'FIO2', 'title1': 'Date', 'title2': 'Cm', 'viewKey': 'FIO2', }, { 'name': 'SAO2', 'title1': 'Date', 'title2': 'Cm', 'viewKey': 'SAO2', }, ]; break; case vitalSignDetails.painScale: VSchart = [ { 'name': 'PainScore', 'title1': 'Date', 'title2': 'Cm', 'viewKey': 'PainScore', }, ]; break; default: } return BaseView( onModelReady: (model) { vitalList = model.patientVitalSignOrderdSubList; }, builder: (_, model, w) => AppScaffold( baseViewModel: model, appBarTitle: pageTitle, body: ListView( children: VSchart.map((chartInfo) { var vitalListTemp = vitalList.where( (element) => element.toJson()[chartInfo['viewKey']] != null, ); return vitalListTemp.length != 0 ? VitalSingChartAndDetials( vitalList: vitalList, name: chartInfo['name'], title1: chartInfo['title1'], title2: chartInfo['title2'], viewKey: chartInfo['viewKey']) : Center( child: Container( margin: EdgeInsets.only( top: MediaQuery.of(context).size.height * 0.45), child: Center( child: DrAppEmbeddedError( error: TranslationBase.of(context).youDoNotHaveAnyItem), ), )); }).toList(), ), ), ); } } \ No newline at end of file +import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; +import 'package:doctor_app_flutter/lookups/patient_lookup.dart'; +import 'package:doctor_app_flutter/models/patient/vital_sign/patient-vital-sign-data.dart'; +import 'package:doctor_app_flutter/models/patient/vital_sign/patient-vital-sign-history.dart'; +import 'package:doctor_app_flutter/screens/patients/profile/vital_sign/vital_sing_chart_and_detials.dart'; +import 'package:doctor_app_flutter/screens/patients/profile/vital_sign/vital_sing_chart_blood_pressure.dart'; +import 'package:doctor_app_flutter/widgets/shared/app_scaffold_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class VitalSignItemDetailsScreen extends StatelessWidget { + final vitalSignDetails pageKey; + final String pageTitle; + List VSchart; + + VitalSignItemDetailsScreen({this.vitalList, this.pageKey, this.pageTitle}); + + final List vitalList; + + @override + Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); + switch (pageKey) { + case vitalSignDetails.BodyMeasurements: + VSchart = [ + { + 'name': 'BMI', + 'nameAr': 'مؤشر الكتلة', + 'title1': 'Date', + 'title2': 'BMI', + 'title2Ar': 'الكتلة', + 'viewKey': 'BodyMassIndex', + }, + + ]; + + break; + + case vitalSignDetails.Temperature: + VSchart = [ + { + 'name': 'Temperature In Celsius', + 'nameAr': 'درجة الحرارة بالدرجة المئوية', + 'title1': 'Date', + 'title2': 'C', + 'title2Ar': 'ْس', + 'viewKey': 'TemperatureCelcius', + }, + ]; + + break; + case vitalSignDetails.Pulse: + VSchart = [ + { + 'name': 'Pulse Beat Per Minute', + 'nameAr': 'نبضة نبضة في الدقيقة', + 'title1': 'Date', + 'title2': 'Minute', + 'title2Ar': 'دقيقة', + 'viewKey': 'PulseBeatPerMinute', + }, + ]; + + break; + case vitalSignDetails.Prescriptions: + VSchart = [ + { + 'name': 'Respiration Beat Per Minute', + 'nameAr': 'ضربات التنفس في الدقيقة', + 'title1': 'Date', + 'title2': 'Beat Per Minute', + 'title2Ar': 'نفس في الدقيقة', + 'viewKey': 'RespirationBeatPerMinute', + }, + ]; + + break; + case vitalSignDetails.BloodPressure: + VSchart = [ + { + 'name': 'Blood Pressure Systolic Diastolic', + 'nameAr': 'ضغط الدم الإنقباض الإنبساط', + 'title1': 'Date', + 'title2': 'systolic', + 'title3': 'Diastolic', + 'title2Ar': 'الإنقباض', + 'title3Ar': 'الإنبساط', + 'viewKey': 'BloodPressure', + }, + + ]; + + break; + case vitalSignDetails.Respiration: + VSchart = [ + { + 'name': 'Respiration Rate', + 'nameAr': 'معدل التنفس', + 'title1': 'Date', + 'title2': 'bpm', + 'title2Ar': 'نفس', + 'viewKey': 'RespirationBeatPerMinute', + }, + ]; + + break; + case vitalSignDetails.heart: + VSchart = [ + { + 'name': 'Heart rate', + 'nameAr': 'معدل النبض بالدقيقة', + 'title1': 'Date', + 'title2': 'bpm', + 'title2Ar': 'نبضة', + 'viewKey': 'PulseBeatPerMinute', + }, + ]; + + break; + case vitalSignDetails.PainScale: + VSchart = [ + { + 'name': 'PainScore', + 'nameAr': 'نقاط الألم', + 'title1': 'Date', + 'title2': 'Cm', + 'title2Ar': 'سم', + 'viewKey': 'PainScore', + }, + ]; + + break; + case vitalSignDetails.Weight: + VSchart = [ + { + 'name': 'Weight Kg', + 'nameAr': 'الوزن كجم', + 'title1': 'Date', + 'title2': 'Kg', + 'title2Ar': 'كجم', + 'viewKey': 'WeightKg', + }, + ]; + + break; + + case vitalSignDetails.Height: + VSchart = [ + { + 'name': 'Height Cm', + 'nameAr': 'الطول سم', + 'title1': 'Date', + 'title2': 'Cm', + 'title2Ar': 'سم', + 'viewKey': 'HeightCm', + }, + ]; + + break; + default: + } + return AppScaffold( + appBarTitle: pageTitle, + isShowAppBar: true, + body: ListView( + children: VSchart.map((chartInfo) { + var vitalListTemp = vitalList.where( + (element) => element.toJson()[chartInfo['viewKey']] != null, + ); + + if(vitalListTemp.length != 0 && chartInfo['viewKey']=='BloodPressure'){ + return VitalSingChartBloodPressure( + vitalList: vitalList, + name:projectViewModel.isArabic? chartInfo['nameAr']:chartInfo['name'], + title1: chartInfo['title1'], + title2:projectViewModel.isArabic?chartInfo['title2Ar']: chartInfo['title2'], + title3:projectViewModel.isArabic?chartInfo['title3Ar']: chartInfo['title3'], + viewKey1: 'BloodPressureHigher', + viewKey2: 'BloodPressureLower', + + ); + } + + return vitalListTemp.length != 0 + ? VitalSingChartAndDetials( + vitalList: vitalList, + name:projectViewModel.isArabic? chartInfo['nameAr']:chartInfo['name'], + title1: chartInfo['title1'], + title2:projectViewModel.isArabic?chartInfo['title2Ar']: chartInfo['title2'], + viewKey: chartInfo['viewKey']) + : Container(); + }).toList(), + ), + ); + } +} diff --git a/lib/screens/patients/profile/vital_sign/vital_sing_chart_and_detials.dart b/lib/screens/patients/profile/vital_sign/vital_sing_chart_and_detials.dart index 7ae4937a..8856e5fe 100644 --- a/lib/screens/patients/profile/vital_sign/vital_sing_chart_and_detials.dart +++ b/lib/screens/patients/profile/vital_sign/vital_sing_chart_and_detials.dart @@ -1,16 +1,14 @@ -import 'package:doctor_app_flutter/models/patient/vital_sign/vital_sign_res_model.dart'; -import 'package:doctor_app_flutter/widgets/patients/vital_sign_details_wideget.dart'; +import 'package:doctor_app_flutter/models/patient/vital_sign/patient-vital-sign-data.dart'; +import 'package:doctor_app_flutter/models/patient/vital_sign/patient-vital-sign-history.dart'; +import 'package:doctor_app_flutter/screens/patients/profile/vital_sign/vital_sign_details_wideget.dart'; +import 'package:doctor_app_flutter/widgets/charts/app_time_series_chart.dart'; import 'package:doctor_app_flutter/widgets/shared/app_expandable_notifier.dart'; -import 'package:doctor_app_flutter/widgets/shared/charts/app_time_series_chart.dart'; import 'package:flutter/material.dart'; -/* - *@author: Elham Rababah - *@Date:03/6/2020 - *@param: - *@return: - *@desc: VitalSingChartAndDetials - */ +import 'package:charts_flutter/flutter.dart' as charts; + +import 'LineChartCurved.dart'; + class VitalSingChartAndDetials extends StatelessWidget { VitalSingChartAndDetials({ Key key, @@ -21,30 +19,46 @@ class VitalSingChartAndDetials extends StatelessWidget { @required this.title2, }) : super(key: key); - final List vitalList; + final List vitalList; final String name; final String viewKey; final String title1; final String title2; + List timeSeriesData = []; @override Widget build(BuildContext context) { + generateData(); return Column( children: [ AppExpandableNotifier( - headerWid: AppTimeSeriesChart( + // isExpand: true, + headerWid: LineChartCurved(title: name,timeSeries:timeSeriesData,indexes: timeSeriesData.length~/5.5,), + bodyWid: VitalSignDetailsWidget( vitalList: vitalList, - chartName: name, + title1: title1, + title2: title2, viewKey: viewKey, ), - bodyWid: VitalSignDetailsWidget( - vitalList: vitalList.reversed.toList(), - title1: '${title1}', - title2: '${title2}', - viewKey: '${viewKey}', - ), ), ], ); } + + generateData() { + if (vitalList.length > 0) { + vitalList.reversed.toList().forEach( + (element) { + if( element.toJson()[viewKey]!=null && element.toJson()[viewKey]?.toInt()!=0) + timeSeriesData.add( + TimeSeriesSales2( + new DateTime(element.vitalSignDate.year, element.vitalSignDate.month, element.vitalSignDate.day), + element.toJson()[viewKey].toDouble(), + ), + ); + }, + ); + } + return timeSeriesData.reversed.toList(); + } } diff --git a/lib/screens/patients/profile/vital_sign/vital_sing_chart_blood_pressure.dart b/lib/screens/patients/profile/vital_sign/vital_sing_chart_blood_pressure.dart new file mode 100644 index 00000000..b94c4ab1 --- /dev/null +++ b/lib/screens/patients/profile/vital_sign/vital_sing_chart_blood_pressure.dart @@ -0,0 +1,85 @@ +import 'package:doctor_app_flutter/models/patient/vital_sign/patient-vital-sign-data.dart'; +import 'package:doctor_app_flutter/models/patient/vital_sign/patient-vital-sign-history.dart'; +import 'package:doctor_app_flutter/screens/patients/profile/vital_sign/vital_sign_details_blood_pressurewideget.dart'; +import 'package:doctor_app_flutter/widgets/charts/app_time_series_chart.dart'; +import 'package:doctor_app_flutter/widgets/shared/app_expandable_notifier.dart'; +import 'package:flutter/material.dart'; + +import 'package:charts_flutter/flutter.dart' as charts; + +import 'LineChartCurved.dart'; +import 'LineChartCurvedBloodPressure.dart'; + +class VitalSingChartBloodPressure extends StatelessWidget { + VitalSingChartBloodPressure({ + Key key, + @required this.vitalList, + @required this.name, + @required this.viewKey1, + @required this.viewKey2, + @required this.title1, + @required this.title2, + @required this.title3, + }) : super(key: key); + + final List vitalList; + final String name; + final String viewKey1; + final String viewKey2; + final String title1; + final String title2; + final String title3; + List timeSeriesData1 = []; + List timeSeriesData2 = []; + + @override + Widget build(BuildContext context) { + generateData(); + return Column( + children: [ + AppExpandableNotifier( + // isExpand: true, + headerWid: LineChartCurvedBloodPressure( + title: name, + timeSeries1: timeSeriesData1, + timeSeries2: timeSeriesData2, + indexes: timeSeriesData1.length ~/ 5.5, + ), + bodyWid: VitalSignBloodPressureWidget( + vitalList: vitalList, + title1: title1, + title2: title2, + title3: title3, + viewKey1: viewKey1, + viewKey2: viewKey2, + ), + ), + ], + ); + } + + generateData() { + if (vitalList.length > 0) { + vitalList.reversed.toList().forEach( + (element) { + if (element.toJson()[viewKey1]?.toInt() != 0) + timeSeriesData1.add( + TimeSeriesSales2( + new DateTime(element.vitalSignDate.year, + element.vitalSignDate.month, element.vitalSignDate.day), + element.toJson()[viewKey1].toDouble(), + ), + ); + if (element.toJson()[viewKey2]?.toInt() != 0) + timeSeriesData2.add( + TimeSeriesSales2( + new DateTime(element.vitalSignDate.year, + element.vitalSignDate.month, element.vitalSignDate.day), + element.toJson()[viewKey2].toDouble(), + ), + ); + }, + ); + } + } +} diff --git a/lib/screens/prescription/add_prescription_form.dart b/lib/screens/prescription/add_prescription_form.dart index c8ff6ce2..0b49c257 100644 --- a/lib/screens/prescription/add_prescription_form.dart +++ b/lib/screens/prescription/add_prescription_form.dart @@ -7,6 +7,7 @@ import 'package:doctor_app_flutter/core/viewModel/prescription_view_model.dart'; import 'package:doctor_app_flutter/models/livecare/transfer_to_admin.dart'; import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart'; import 'package:doctor_app_flutter/screens/base/base_view.dart'; +import 'package:doctor_app_flutter/screens/prescription/drugtodrug.dart'; import 'package:doctor_app_flutter/screens/prescription/prescription_screen.dart'; import 'package:doctor_app_flutter/screens/prescription/prescription_warnings.dart'; import 'package:doctor_app_flutter/util/date-utils.dart'; @@ -713,7 +714,8 @@ class _PrescriptionFormWidgetState extends State { .addMedication, onPressed: () { formKey.currentState.save(); - + // Navigator.pop(context); + // openDrugToDrug(); if (strength == null || route == null || frequency == null || @@ -728,26 +730,8 @@ class _PrescriptionFormWidgetState extends State { } if (formKey.currentState.validate()) { - postProcedure( - patient: widget.patient, - doseTimeIn: - doseTime['id'].toString(), - model: widget.model, - duration: - duration['id'].toString(), - frequency: - frequency['id'].toString(), - route: route['id'].toString(), - drugId: selectedDrug['ItemId'] - .toString(), - strength: - strength['id'].toString(), - indication: - indicationController.text, - instruction: - instructionController.text, - doseTime: selectedDate); Navigator.pop(context); + openDrugToDrug(); } { // Navigator.push( @@ -824,4 +808,44 @@ class _PrescriptionFormWidgetState extends State { ), ); } + + openDrugToDrug() { + showModalBottomSheet( + context: context, + builder: (context) { + return Container( + height: SizeConfig.realScreenHeight * .5, + width: SizeConfig.realScreenWidth, + child: SingleChildScrollView( + child: Column( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + DrugToDrug(widget.patient), + Container( + margin: EdgeInsets.all(SizeConfig.widthMultiplier * 2), + child: AppButton( + title: TranslationBase.of(context).addMedication, + onPressed: () { + postProcedure( + patient: widget.patient, + doseTimeIn: doseTime['id'].toString(), + model: widget.model, + duration: duration['id'].toString(), + frequency: frequency['id'].toString(), + route: route['id'].toString(), + drugId: selectedDrug['ItemId'].toString(), + strength: strength['id'].toString(), + indication: indicationController.text, + instruction: instructionController.text, + doseTime: selectedDate); + }, + )) + ], + )), + + //], + //) + ); + }); + } } diff --git a/lib/screens/prescription/drugtodrug.dart b/lib/screens/prescription/drugtodrug.dart new file mode 100644 index 00000000..8f51da80 --- /dev/null +++ b/lib/screens/prescription/drugtodrug.dart @@ -0,0 +1,89 @@ +import 'package:doctor_app_flutter/config/shared_pref_kay.dart'; +import 'package:doctor_app_flutter/config/size_config.dart'; +import 'package:doctor_app_flutter/core/viewModel/SOAP_view_model.dart'; +import 'package:doctor_app_flutter/core/viewModel/patient-vital-sign-viewmodel.dart'; +import 'package:doctor_app_flutter/core/viewModel/patient_view_model.dart'; +import 'package:doctor_app_flutter/core/viewModel/prescription_view_model.dart'; +import 'package:doctor_app_flutter/models/SOAP/GeneralGetReqForSOAP.dart'; +import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart'; +import 'package:doctor_app_flutter/models/patient/vital_sign/vital_sign_req_model.dart'; +import 'package:doctor_app_flutter/screens/base/base_view.dart'; +import 'package:doctor_app_flutter/screens/medicine/medicine_search_screen.dart'; +import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; +import 'package:doctor_app_flutter/widgets/shared/app_scaffold_widget.dart'; +import 'package:doctor_app_flutter/widgets/shared/network_base_view.dart'; +import 'package:flutter/material.dart'; + +class DrugToDrug extends StatefulWidget { + final PatiantInformtion patient; + DrugToDrug(this.patient); + @override + _DrugToDrug createState() => _DrugToDrug(); +} + +class _DrugToDrug extends State { + int typeID = 1; + List> expandableList = [ + {'name': 'CRITICAL'}, + {'name': 'HIGH'}, + {'name': 'MODERATE'}, + {'name': 'LOW'}, + {'name': 'INFO'}, + ]; + + @override + void initState() { + getTypeID(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + GeneralGetReqForSOAP generalGetReqForSOAP = GeneralGetReqForSOAP( + patientMRN: 2954208, //widget.patient.patientMRN, + episodeId: 210011002, //widget.patient.episodeNo, + appointmentNo: 2016055308, //widget.patient.appointmentNo, + doctorID: '', + editedBy: ''); + + return BaseView( + onModelReady: (model) => model.getPatientVitalSign(widget.patient), + builder: (BuildContext context, model, Widget child) { + return BaseView( + onModelReady: (model2) => + model2.getPatientAllergy(generalGetReqForSOAP), + builder: (BuildContext context, model2, Widget child) { + return BaseView( + onModelReady: (model3) => model3.getDrugToDrug( + model.patientVitalSigns, model2.patientAllergiesList), + builder: (BuildContext context, + PrescriptionViewModel model3, Widget child) => + NetworkBaseView( + baseViewModel: model3, + child: Container( + height: SizeConfig.realScreenHeight * .45, + child: new ListView.builder( + itemCount: expandableList.length, + itemBuilder: (context, i) { + return new ExpansionTile( + title: new Text( + expandableList[i]['name'], + style: new TextStyle( + fontSize: 20.0, + fontWeight: FontWeight.bold, + fontStyle: FontStyle.italic), + ), + children: [Text('Hi')], + ); + })))); + }); + }); + } + + getTypeID() async { + var type = await sharedPref.getString(SLECTED_PATIENT_TYPE) == '0' ? 2 : 1; + setState(() { + typeID = type; + }); + } +} diff --git a/lib/screens/reschedule-leaves/reschedule_leave.dart b/lib/screens/reschedule-leaves/reschedule_leave.dart index 6f3299d1..5d546c04 100644 --- a/lib/screens/reschedule-leaves/reschedule_leave.dart +++ b/lib/screens/reschedule-leaves/reschedule_leave.dart @@ -792,7 +792,7 @@ class _RescheduleLeaveScreen extends State { "doctorId": this.profile['DoctorID'], "dateTimeFrom": fromDate, "dateTimeTo": toDate, - "date": df.format(DateTime.now()), + "date": offTime == '1' ? fromDate : df.format(DateTime.now()), "reasonId": reason == null ? model.allOffTime[0]['code'] : reason, "coveringDoctorId": doctorID == null ? model.coveringDoctors[0]['doctorID'] : doctorID, @@ -846,7 +846,7 @@ class _RescheduleLeaveScreen extends State { "doctorId": this.profile['DoctorID'], "dateTimeFrom": fromDate, "dateTimeTo": toDate, - "date": df.format(DateTime.now()), + "date": offTime == '1' ? fromDate : df.format(DateTime.now()), "reasonId": reason == null ? model.allOffTime[0]['code'] : reason, "coveringDoctorId": doctorID == null ? model.coveringDoctors[0]['doctorID'] : doctorID, diff --git a/lib/util/date-utils.dart b/lib/util/date-utils.dart index 5d651bad..df52b1fd 100644 --- a/lib/util/date-utils.dart +++ b/lib/util/date-utils.dart @@ -77,5 +77,138 @@ class DateUtils { int.parse(str.substring(startIndex + start.length, endIndex))); return differenceBetweenDateAndCurrent(date); } + + /// get month by + /// [weekDay] convert week day in int to week day name + static getWeekDay(int weekDay) { + switch (weekDay) { + case 1: + return "Monday"; + case 2: + return "Tuesday"; + case 3: + return "Wednesday"; + case 4: + return "Thursday"; + case 5: + return "Friday"; + case 6: + return "Saturday "; + case 7: + return "Sunday"; + } + } + + /// get month by + /// [weekDay] convert week day in int to week day name arabic + static getWeekDayArabic(int weekDay) { + switch (weekDay) { + case 1: + return "الاثنين"; + case 2: + return "الثلاثاء"; + case 3: + return "الاربعاء"; + case 4: + return "الخميس"; + case 5: + return "الجمعه"; + case 6: + return "السبت "; + case 7: + return "الاحد"; + } + } + + /// get month by + /// [month] convert month number in to month name + static getMonth(int month) { + switch (month) { + case 1: + return "January"; + case 2: + return "February"; + case 3: + return "March"; + case 4: + return "April"; + case 5: + return "May"; + case 6: + return "June"; + case 7: + return "July"; + case 8: + return "August"; + case 9: + return "September"; + case 10: + return "October"; + case 11: + return "November"; + case 12: + return "December"; + } + } + + /// get month by + /// [month] convert month number in to month name in Arabic + static getMonthArabic(int month) { + switch (month) { + case 1: + return "يناير"; + case 2: + return " فبراير"; + case 3: + return "مارس"; + case 4: + return "أبريل"; + case 5: + return "مايو"; + case 6: + return "يونيو"; + case 7: + return "يوليو"; + case 8: + return "أغسطس"; + case 9: + return "سبتمبر"; + case 10: + return " اكتوبر"; + case 11: + return " نوفمبر"; + case 12: + return "ديسمبر"; + } + } + + static getMonthByName(String month) { + switch (month.toLowerCase()) { + case 'january': + return 1; + case 'february': + return 2; + case 'march': + return 3; + case 'april': + return 4; + case 'may': + return 5; + case 'june': + return 6; + case 'july': + return 7; + case 'august': + return 8; + case 'september': + return 9; + case 'october': + return 10; + case 'november': + return 11; + case 'december': + return 12; + } + } } diff --git a/lib/util/helpers.dart b/lib/util/helpers.dart index 9a398949..a7229ca2 100644 --- a/lib/util/helpers.dart +++ b/lib/util/helpers.dart @@ -346,15 +346,17 @@ class Helpers { } logout() async { + DEVICE_TOKEN = ""; String lang = await sharedPref.getString(APP_Language); await clearSharedPref(); sharedPref.setString(APP_Language, lang); Navigator.of(AppGlobal.CONTEX).pushReplacementNamed(LOGIN); + // TODO Fix it // Navigator.of(AppGlobal.CONTEX).popUntil((ModalRoute.withName(LOGIN))); } - String parseHtmlString(String htmlString) { + String parseHtmlString(String htmlString) { final document = parse(htmlString); final String parsedString = parse(document.body.text).documentElement.text; @@ -380,11 +382,11 @@ class Helpers { hintText: selectedText != null ? selectedText : hintText, suffixIcon: isDropDown ? suffixIcon != null - ? suffixIcon - : Icon( - Icons.arrow_drop_down, - color: dropDownColor != null ? dropDownColor : Colors.black, - ) + ? suffixIcon + : Icon( + Icons.arrow_drop_down, + color: dropDownColor != null ? dropDownColor : Colors.black, + ) : null, hintStyle: TextStyle( fontSize: 14, @@ -394,7 +396,8 @@ class Helpers { } static BoxDecoration containerBorderDecoration( - Color containerColor, Color borderColor, {double borderWidth = -1}) { + Color containerColor, Color borderColor, + {double borderWidth = -1}) { return BoxDecoration( color: containerColor, shape: BoxShape.rectangle, diff --git a/lib/util/translations_delegate_base.dart b/lib/util/translations_delegate_base.dart index 4c03e7b4..aae8e091 100644 --- a/lib/util/translations_delegate_base.dart +++ b/lib/util/translations_delegate_base.dart @@ -555,9 +555,75 @@ class TranslationBase { localizedValues['approvalRequired'][locale.languageCode]; String get uncoveredByDoctor => localizedValues['uncoveredByDoctor'][locale.languageCode]; + String get chiefComplaintEmptyMsg => + localizedValues['chiefComplaintEmptyMsg'][locale.languageCode]; + + String get moreVerification => + localizedValues['more-verify'][locale.languageCode]; + + String get welcomeBack => + localizedValues['welcome-back'][locale.languageCode]; + + String get accountInfo => + localizedValues['account-info'][locale.languageCode]; + + String get useAnotherAccount => + localizedValues['another-acc'][locale.languageCode]; + + String get verifyLoginWith => + localizedValues['verify-login-with'][locale.languageCode]; + + String get register => localizedValues['register-user'][locale.languageCode]; + + String get verifyFingerprint => + localizedValues['verify-with-fingerprint'][locale.languageCode]; + + String get verifyFaceID => + localizedValues['verify-with-faceid'][locale.languageCode]; + + String get verifySMS => + localizedValues['verify-with-sms'][locale.languageCode]; + + String get verifyWhatsApp => + localizedValues['verify-with-whatsapp'][locale.languageCode]; + + String get lastLoginAt => localizedValues['last-login'][locale.languageCode]; + + String get lastLoginWith => + localizedValues['last-login-with'][locale.languageCode]; + + String get verifyFingerprint2 => + localizedValues['verify-fingerprint'][locale.languageCode]; + String get verificationMessage => + localizedValues['verification_message'][locale.languageCode]; + String get validationMessage => + localizedValues['validation_message'][locale.languageCode]; + String get addAssessment => localizedValues['addAssessment'][locale.languageCode]; String get assessment => localizedValues['assessment'][locale.languageCode]; + + String get physicalSystemExamination => + localizedValues['physicalSystemExamination'][locale.languageCode]; + String get searchExamination => + localizedValues['searchExamination'][locale.languageCode]; + String get addExamination => + localizedValues['addExamination'][locale.languageCode]; + String get doc => localizedValues['doc'][locale.languageCode]; + String get patientNoDetailErrMsg => + localizedValues['patientNoDetailErrMsg'][locale.languageCode]; + String get systolicLng => localizedValues['systolic-lng'][locale.languageCode]; + String get diastolicLng => localizedValues['diastolic-lng'][locale.languageCode]; + String get mass => localizedValues['mass'][locale.languageCode]; + String get tempC => localizedValues['temp-c'][locale.languageCode]; + String get bpm => localizedValues['bpm'][locale.languageCode]; + String get respirationSigns => + localizedValues['respiration-signs'][locale.languageCode]; + String get sysDias => localizedValues['sys-dias'][locale.languageCode]; + String get body => localizedValues['body'][locale.languageCode]; + String get respirationRate => + localizedValues['respirationRate'][locale.languageCode]; + String get heart => localizedValues['heart'][locale.languageCode]; String get chiefComplaintEmptyMsg => localizedValues['chiefComplaintEmptyMsg'][locale.languageCode]; String get physicalSystemExamination => diff --git a/lib/widgets/auth/known_user_login.dart b/lib/widgets/auth/known_user_login.dart index 4df37d66..b181aed8 100644 --- a/lib/widgets/auth/known_user_login.dart +++ b/lib/widgets/auth/known_user_login.dart @@ -70,8 +70,8 @@ class _KnownUserLoginState extends State { @override Widget build(BuildContext context) { AuthViewModel authProv = Provider.of(context); - var imeiModel = {'IMEI': _platformImei}; - _loginTypeFuture = authProv.selectDeviceImei(imeiModel); + // var imeiModel = {'IMEI': _platformImei}; + // _loginTypeFuture = authProv.selectDeviceImei(imeiModel); return FutureBuilder( future: Future.wait([_loggedUserFuture, _loginTypeFuture]), builder: (BuildContext context, AsyncSnapshot snapshot) { diff --git a/lib/widgets/auth/login_form.dart b/lib/widgets/auth/login_form.dart index 808b1763..3aac5cdd 100644 --- a/lib/widgets/auth/login_form.dart +++ b/lib/widgets/auth/login_form.dart @@ -224,26 +224,29 @@ class _LoginFormState extends State { } login(context, AuthViewModel authProv, Function changeLoadingStata) { - FocusScopeNode currentFocus = FocusScope.of(context); - changeLoadingStata(true); + showLoading(); if (loginFormKey.currentState.validate()) { loginFormKey.currentState.save(); sharedPref.setInt(PROJECT_ID, userInfo.projectID); authProv.login(userInfo).then((res) { - changeLoadingStata(false); - + //changeLoadingStata(false); + hideLoading(); if (res['MessageStatus'] == 1) { // insertDeviceImei(res, authProv); saveObjToString(LOGGED_IN_USER, res); + sharedPref.remove(LAST_LOGIN_USER); sharedPref.setString(TOKEN, res['LogInTokenID']); print("token" + res['LogInTokenID']); - Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (BuildContext context) => VerificationMethodsScreen(password: userInfo.password,))); + Navigator.of(context).pushReplacement(MaterialPageRoute( + builder: (BuildContext context) => VerificationMethodsScreen( + password: userInfo.password, + ))); } else { // handel error helpers.showErrorToast(res['ErrorEndUserMessage']); } }).catchError((err) { - print('$err'); + hideLoading(); changeLoadingStata(false); helpers.showErrorToast(err); }); @@ -273,7 +276,11 @@ class _LoginFormState extends State { if (res['MessageStatus'] == 1) { setSharedPref('platformImei', _platformImei); saveObjToString(LOGGED_IN_USER, preRes); - Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (BuildContext context) => VerificationMethodsScreen(password: userInfo.password,))); + + Navigator.of(context).pushReplacement(MaterialPageRoute( + builder: (BuildContext context) => VerificationMethodsScreen( + password: userInfo.password, + ))); // save imei on shared preferance } else { @@ -350,4 +357,18 @@ class _LoginFormState extends State { primaryFocus.unfocus(); } + + showLoading() { + showDialog( + context: context, + builder: (BuildContext context) { + return Center( + child: CircularProgressIndicator(), + ); + }); + } + + hideLoading() { + Navigator.pop(context); + } } diff --git a/lib/widgets/auth/verification_methods.dart b/lib/widgets/auth/verification_methods.dart index 32c541a3..caee190d 100644 --- a/lib/widgets/auth/verification_methods.dart +++ b/lib/widgets/auth/verification_methods.dart @@ -1,11 +1,23 @@ import 'dart:io' show Platform; import 'package:doctor_app_flutter/config/shared_pref_kay.dart'; +import 'package:doctor_app_flutter/core/model/imei_details.dart'; +import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; import 'package:doctor_app_flutter/models/auth/activation_Code_req_model.dart'; -import 'package:doctor_app_flutter/screens/auth/verification_methods_screen.dart'; +import 'package:doctor_app_flutter/models/auth/check_activation_code_request_model.dart'; +import 'package:doctor_app_flutter/models/auth/send_activation_code_model2.dart'; +import 'package:doctor_app_flutter/models/doctor/clinic_model.dart'; +import 'package:doctor_app_flutter/models/doctor/doctor_profile_model.dart'; +import 'package:doctor_app_flutter/models/doctor/profile_req_Model.dart'; import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; +import 'package:doctor_app_flutter/widgets/otp/sms-popup.dart'; +import 'package:doctor_app_flutter/widgets/shared/app_button.dart'; +import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; +import 'package:doctor_app_flutter/widgets/shared/rounded_container_widget.dart'; import 'package:flutter/material.dart'; -import 'package:hexcolor/hexcolor.dart'; +import 'package:flutter/services.dart'; +import 'package:intl/intl.dart'; +import 'package:local_auth/local_auth.dart'; import 'package:provider/provider.dart'; import '../../config/size_config.dart'; @@ -40,6 +52,17 @@ class _VerificationMethodsState extends State { Future _loggedUserFuture; var _loggedUser; var verificationMethod; + GetIMEIDetailsModel user; + final LocalAuthentication auth = LocalAuthentication(); + var _availableBiometrics; + ProjectViewModel projectsProvider; + var isMoreOption = false; + var onlySMSBox = false; + static BuildContext _context; + var loginTokenID; + + bool authenticated; + @override void initState() { super.initState(); @@ -50,6 +73,13 @@ class _VerificationMethodsState extends State { sharedPref.getObj(LOGGED_IN_USER).then((userInfo) { _loggedUser = userInfo; }); + sharedPref.getObj(LAST_LOGIN_USER).then((lastLogin) { + if (lastLogin != null) { + user = GetIMEIDetailsModel.fromJson(lastLogin); + } + }); + + print(user); } @override @@ -63,6 +93,7 @@ class _VerificationMethodsState extends State { @override Widget build(BuildContext context) { AuthViewModel authProv = Provider.of(context); + projectsProvider = Provider.of(context); return FutureBuilder( future: Future.wait([_loggedUserFuture]), builder: (BuildContext context, AsyncSnapshot snapshot) { @@ -75,66 +106,205 @@ class _VerificationMethodsState extends State { return Text('Error: ${snapshot.error}'); } else { return Container( - width: SizeConfig.realScreenWidth * 0.80, + width: SizeConfig.realScreenWidth, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - hideSilentMethods() - ? TranslationBase.of(context).firstStep - : TranslationBase.of(context).pleaseChoose, - style: TextStyle( - fontSize: 3.5 * SizeConfig.textMultiplier, - ), - ), - SizedBox( - height: 20, - ), Container( - height: SizeConfig.realScreenHeight * 0.6, - child: CustomScrollView( - primary: false, - slivers: [ - SliverPadding( - padding: const EdgeInsets.all(0), - sliver: SliverGrid.count( - // childAspectRatio: 0.7, - crossAxisSpacing: 0, - mainAxisSpacing: 5, - crossAxisCount: 2, - children: [ - Visibility( - visible: hideSilentMethods() ? false : true, - child: buildFingerprintMethod( - context, authProv), - replacement: - buildWhatsAppMethod(context, authProv), - ), - Visibility( - visible: hideSilentMethods() ? false : true, - child: buildFaceIDMethod(context, authProv), - replacement: - buildSMSMethod(context, authProv), - ), - Visibility( - visible: - hideSilentMethods() ? false : true, - child: buildWhatsAppMethod( - context, authProv)), - Visibility( - visible: hideSilentMethods() ? false : true, - child: buildSMSMethod(context, authProv), - ), - ], - ), - ), - ], - ), - // height: 500, - ), - SizedBox( - // height: 20, - ) + height: SizeConfig.realScreenHeight * 0.6, + child: Column( + children: [ + user != null && isMoreOption == false + ? Column( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + AppText( + TranslationBase.of(context) + .welcomeBack + + ' ' + + user.doctorName, + fontSize: + SizeConfig.textMultiplier * 3.5, + ), + SizedBox( + height: 20, + ), + AppText( + TranslationBase.of(context) + .accountInfo, + fontSize: + SizeConfig.textMultiplier * 2.5, + ), + SizedBox( + height: 20, + ), + Card( + color: Colors.grey[300], + child: Row( + children: [ + Flexible( + child: ListTile( + title: Text( + TranslationBase.of(context) + .lastLoginAt, + textAlign: TextAlign.center, + overflow: + TextOverflow.ellipsis, + ), + subtitle: Text( + // user. != null + // ? formatDate(Helpers + // .convertStringToDate( + // user + // .)) + // : user != + // null + // ? formatDate(Helpers + // .convertStringToDate(user + // .createdOn)) + //: + '--', + overflow: + TextOverflow.ellipsis, + textAlign: + TextAlign.center), + )), + Flexible( + child: ListTile( + title: Text( + TranslationBase.of( + context) + .lastLoginWith, + overflow: + TextOverflow.ellipsis, + textAlign: + TextAlign.center), + subtitle: Text( + getType(user.logInTypeID, + context), + overflow: + TextOverflow.ellipsis, + textAlign: + TextAlign.center), + )) + ], + )), + ], + ) + : Column( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + this.onlySMSBox == false + ? AppText( + TranslationBase.of(context) + .verifyLoginWith, + fontSize: SizeConfig + .textMultiplier * + 3.5, + textAlign: TextAlign.left, + ) + : AppText( + TranslationBase.of(context) + .verifyFingerprint2, + fontSize: SizeConfig + .textMultiplier * + 2.5, + textAlign: TextAlign.start, + ), + ]), + user != null && isMoreOption == false + ? Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Expanded( + child: InkWell( + onTap: () => { + authenticateUser( + 3, + BiometricType + .face + .index, + authProv) + }, + child: getButton( + user.logInTypeID, + authProv))), + Expanded( + child: + getButton(5, authProv)) + ]) + ]) + : Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + onlySMSBox == false + ? Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Expanded( + child: getButton( + 3, authProv)), + Expanded( + child: getButton( + 2, authProv)) + ], + ) + : SizedBox(), + Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Expanded( + child: + getButton(1, authProv)), + Expanded( + child: getButton(4, authProv)) + ], + ), + ]), + Expanded( + flex: 1, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + user != null + ? Row( + children: [ + Expanded( + child: Button( + title: + TranslationBase.of(context) + .useAnotherAccount, + onTap: () { + Navigator.of(context) + .pushNamed(LOGIN); + }, + )), + ], + ) + : SizedBox(), + ], + ), + ) + ], + )) ], ), ); @@ -143,119 +313,6 @@ class _VerificationMethodsState extends State { }); } - /* - *@author: Elham Rababah - *@Date:28/5/2020 - *@param: BuildContext context, AuthProvider authProv - *@return: Center widget - *@desc: buildSMSMethod Methods widget - */ - Center buildSMSMethod(BuildContext context, AuthViewModel authProv) { - return buildVerificationMethod( - context, - 'assets/images/verification_sms_icon.png', - TranslationBase.of(context).sms, () { - sendActivationCodeByOtpNotificationType(1, authProv); - }); - } - - /* - *@author: Elham Rababah - *@Date:28/5/2020 - *@param: BuildContext context, AuthProvider authProv - *@return: Center widget - *@desc: build WhatsApp Methods widget - */ - Center buildWhatsAppMethod(BuildContext context, AuthViewModel authProv) { - return buildVerificationMethod( - context, - 'assets/images/verification_whatsapp_icon.png', - TranslationBase.of(context).whatsApp, () { - sendActivationCodeByOtpNotificationType(2, authProv); - }); - } - -/* - *@author: Elham Rababah - *@Date:28/5/2020 - *@param: BuildContext context, AuthProvider authProv - *@return: Center widget - *@desc: build FaceID Methods widget - */ - Center buildFaceIDMethod(BuildContext context, AuthViewModel authProv) { - return buildVerificationMethod( - context, - 'assets/images/verification_faceid_icon.png', - TranslationBase.of(context).faceId, () { - sendActivationCodeByOtpNotificationType(3, authProv); - }); - } - -/* - *@author: Elham Rababah - *@Date:28/5/2020 - *@param: BuildContext context, AuthProvider authProv - *@return: Center widget - *@desc: build Fingerprint Methods widget - */ - Center buildFingerprintMethod(BuildContext context, AuthViewModel authProv) { - return buildVerificationMethod( - context, - 'assets/images/verification_fingerprint_icon.png', - TranslationBase.of(context).fingerprint, () { - sendActivationCodeByOtpNotificationType(4, authProv); - }); - } - - /* - *@author: Elham Rababah - *@Date:28/5/2020 - *@param: BuildContext context, AuthProvider authProv - *@return: Center widget - *@desc: build Verification Methods widget - */ - Center buildVerificationMethod(context, url, dec, Function fun) { - return Center( - child: InkWell( - onTap: fun, - child: Container( - // height: SizeConfig.heightMultiplier *2, - height: SizeConfig.heightMultiplier * 19, - width: SizeConfig.widthMultiplier * 37, - - padding: EdgeInsets.all(10), - decoration: BoxDecoration( - border: Border.all( - width: 1, - color: HexColor( - '#CCCCCC') // <--- border width here - ), - borderRadius: BorderRadius.all(Radius.circular(10))), - child: Column( - children: [ - Container( - margin: EdgeInsetsDirectional.only( - top: SizeConfig.heightMultiplier * 0.5), - child: Image.asset( - url, - height: SizeConfig.heightMultiplier * 10, - fit: BoxFit.cover, - ), - ), - SizedBox( - height: 10, - ), - Text( - dec, - style: TextStyle(fontSize: SizeConfig.textMultiplier * 2), - ) - ], - ), - ), - ), - ); - } - bool hideSilentMethods() { return verificationMethod == 4 || verificationMethod == 3 ? true : false; } @@ -267,64 +324,518 @@ class _VerificationMethodsState extends State { *@return: *@desc: send Activation Code By Otp Notification Type */ - sendActivationCodeByOtpNotificationType(oTPSendType, AuthViewModel authProv) async { + sendActivationCodeByOtpNotificationType( + oTPSendType, AuthViewModel authProv) async { // TODO : build enum for verfication method if (oTPSendType == 1 || oTPSendType == 2) { widget.changeLoadingStata(true); int projectID = await sharedPref.getInt(PROJECT_ID); ActivationCodeModel activationCodeModel = ActivationCodeModel( facilityId: projectID, - generalid: "Cs2020@2016\$2958", memberID: _loggedUser['List_MemberInformation'][0]['MemberID'], zipCode: _loggedUser['ZipCode'], mobileNumber: _loggedUser['MobileNumber'], - + otpSendType: oTPSendType.toString(), password: widget.password); - Map model = { - - "OTP_SendType": oTPSendType - }; - try { authProv .sendActivationCodeForDoctorApp(activationCodeModel) .then((res) { - widget.changeLoadingStata(false); - - if (res['MessageStatus'] == 1) { - print("VerificationCode : "+ res["VerificationCode"]); - sharedPref.setString(VIDA_AUTH_TOKEN_ID, res["VidaAuthTokenID"]); - sharedPref.setString(VIDA_REFRESH_TOKEN_ID, res["VidaRefreshTokenID"]); - sharedPref.setString(LOGIN_TOKEN_ID, res["LogInTokenID"]); - Navigator.of(context).pushReplacementNamed(VERIFY_ACCOUNT, - arguments: {'model': model}); - } else { - print(res['ErrorEndUserMessage']); - helpers.showErrorToast(res['ErrorEndUserMessage']); - } - }) - .catchError((err) { + widget.changeLoadingStata(false); + + if (res['MessageStatus'] == 1) { + print("VerificationCode : " + res["VerificationCode"]); + sharedPref.setString(VIDA_AUTH_TOKEN_ID, res["VidaAuthTokenID"]); + sharedPref.setString( + VIDA_REFRESH_TOKEN_ID, res["VidaRefreshTokenID"]); + sharedPref.setString(LOGIN_TOKEN_ID, res["LogInTokenID"]); + this.startSMSService(oTPSendType, authProv); + } else { + print(res['ErrorEndUserMessage']); + helpers.showErrorToast(res['ErrorEndUserMessage']); + } + }).catchError((err) { print('$err'); widget.changeLoadingStata(false); helpers.showErrorToast(); }); } catch (e) {} + } else { + // TODO route to this page with parameters to inicate we should present 2 option + if (Platform.isAndroid && oTPSendType == 3) { + helpers.showErrorToast('Your device not support this feature'); + } else { + // Navigator.of(context).push(MaterialPageRoute( + // builder: (BuildContext context) => + // VerificationMethodsScreen(password: widget.password,))); + + // Navigator.of(context).pushNamed(VERIFICATION_METHODS, + // arguments: {'verificationMethod': oTPSendType}); + } + } + } + + sendActivationCodeVerificationScreen( + oTPSendType, AuthViewModel authProv) async { + // TODO : build enum for verfication method + if (oTPSendType == 1 || oTPSendType == 2) { + widget.changeLoadingStata(true); + ActivationCodeModel2 activationCodeModel = ActivationCodeModel2( + facilityId: user.projectID, + memberID: user.doctorID, + zipCode: user.outSA == true ? '971' : '966', + mobileNumber: user.mobile, + oTPSendType: oTPSendType, + isMobileFingerPrint: 1, + vidaAuthTokenID: user.vidaAuthTokenID, + vidaRefreshTokenID: user.vidaRefreshTokenID); + try { + authProv + .sendActivationCodeVerificationScreen(activationCodeModel) + .then((res) { + widget.changeLoadingStata(false); + + if (res['MessageStatus'] == 1) { + print("VerificationCode : " + res["VerificationCode"]); + sharedPref.setString(VIDA_AUTH_TOKEN_ID, res["VidaAuthTokenID"]); + sharedPref.setString( + VIDA_REFRESH_TOKEN_ID, res["VidaRefreshTokenID"]); + sharedPref.setString(LOGIN_TOKEN_ID, res["LogInTokenID"]); + this.startSMSService(oTPSendType, authProv); + } else { + print(res['ErrorEndUserMessage']); + helpers.showErrorToast(res['ErrorEndUserMessage']); + } + }).catchError((err) { + print('$err'); + widget.changeLoadingStata(false); + helpers.showErrorToast(); + }); + } catch (e) {} } else { // TODO route to this page with parameters to inicate we should present 2 option if (Platform.isAndroid && oTPSendType == 3) { helpers.showErrorToast('Your device not support this feature'); } else { - Navigator.of(context).push(MaterialPageRoute( - builder: (BuildContext context) => - VerificationMethodsScreen(password: widget.password,))); + // Navigator.of(context).push(MaterialPageRoute( + // builder: (BuildContext context) => + // VerificationMethodsScreen(password: widget.password,))); // Navigator.of(context).pushNamed(VERIFICATION_METHODS, // arguments: {'verificationMethod': oTPSendType}); } } } + + Widget getButton(flag, authProv) { + switch (flag) { + case 2: + return InkWell( + onTap: () => {authenticateUser(2, true, authProv)}, + child: RoundedContainer( + borderColor: Colors.grey, + showBorder: true, + child: Padding( + padding: EdgeInsets.fromLTRB(30, 15, 30, 15), + child: Column( + children: [ + Image.asset( + 'assets/images/login/104.png', + height: SizeConfig.imageSizeMultiplier * 13, + width: SizeConfig.imageSizeMultiplier * 16, + ), + SizedBox( + height: 20, + ), + AppText( + TranslationBase.of(context).verifyWhatsApp, + fontSize: SizeConfig.textMultiplier * 2, + textAlign: TextAlign.center, + ) + ], + ), + ))); + break; + case 1: + return InkWell( + onTap: () => {authenticateUser(1, true, authProv)}, + child: RoundedContainer( + borderColor: Colors.grey, + showBorder: true, + child: Padding( + padding: EdgeInsets.fromLTRB(5, 15, 5, 15), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/login/103.png', + height: SizeConfig.imageSizeMultiplier * 13, + width: SizeConfig.imageSizeMultiplier * 16, + ), + projectsProvider.isArabic + ? SizedBox( + height: 20, + ) + : SizedBox( + height: 20, + ), + AppText( + TranslationBase.of(context).verifySMS, + fontSize: projectsProvider.isArabic + ? SizeConfig.textMultiplier * 1.8 + : SizeConfig.textMultiplier * 2, + textAlign: TextAlign.center, + ) + ], + ), + ))); + break; + case 3: + return InkWell( + onTap: () => { + authenticateUser(3, BiometricType.fingerprint.index, authProv) + }, + child: RoundedContainer( + backgroundColor: BiometricType.fingerprint.index == 1 + ? Colors.white + : Colors.white.withOpacity(.7), + borderColor: Colors.grey, + showBorder: true, + child: Padding( + padding: EdgeInsets.fromLTRB(5, 15, 5, 15), + child: Column( + children: [ + Image.asset( + 'assets/images/login/102.png', + height: SizeConfig.imageSizeMultiplier * 13, + width: SizeConfig.imageSizeMultiplier * 16, + ), + SizedBox( + height: 20, + ), + AppText( + TranslationBase.of(context).verifyFingerprint, + fontSize: SizeConfig.textMultiplier * 2, + textAlign: TextAlign.center, + ) + ], + ), + ))); + break; + case 4: + return InkWell( + onTap: () => + {authenticateUser(4, BiometricType.face.index, authProv)}, + child: RoundedContainer( + backgroundColor: checkIfBiometricAvailable(BiometricType.face) + ? Colors.white + : Colors.white.withOpacity(.7), + borderColor: Colors.grey, + showBorder: true, + child: Padding( + padding: EdgeInsets.fromLTRB(5, 15, 5, 15), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/login/101.png', + height: SizeConfig.imageSizeMultiplier * 13, + width: SizeConfig.imageSizeMultiplier * 16, + ), + SizedBox( + height: 20, + ), + AppText( + TranslationBase.of(context).verifyFaceID, + fontSize: SizeConfig.textMultiplier * 2, + textAlign: TextAlign.center, + ) + ], + ), + ))); + break; + + default: + return InkWell( + onTap: () => { + setState(() { + isMoreOption = true; + }) + }, + child: RoundedContainer( + backgroundColor: BiometricType.fingerprint.index == 1 + ? Colors.white + : Colors.white.withOpacity(.7), + borderColor: Colors.grey, + showBorder: true, + child: Padding( + padding: EdgeInsets.fromLTRB(5, 0, 5, 5), + child: Column( + children: [ + Image.asset( + 'assets/images/login/more_icon.png', + height: SizeConfig.imageSizeMultiplier * 13, + width: SizeConfig.imageSizeMultiplier * 16, + ), + projectsProvider.isArabic + ? SizedBox( + height: 15, + ) + : SizedBox( + height: 10, + ), + AppText( + TranslationBase.of(context).moreVerification, + fontSize: SizeConfig.textMultiplier * 2, + textAlign: TextAlign.center, + ) + ], + ), + ))); + } + } + + getType(type, context) { + switch (type) { + case 1: + return TranslationBase.of(context).verifySMS; + break; + case 3: + return TranslationBase.of(context).verifyFingerprint; + break; + case 4: + return TranslationBase.of(context).verifyFaceID; + break; + case 2: + return TranslationBase.of(context).verifyWhatsApp; + break; + default: + return TranslationBase.of(context).verifySMS; + break; + } + } + + bool checkIfBiometricAvailable(BiometricType biometricType) { + bool isAvailable = false; + if (_availableBiometrics != null) { + for (var i = 0; i < _availableBiometrics.length; i++) { + if (biometricType == _availableBiometrics[i]) isAvailable = true; + } + } + return isAvailable; + } + + formatDate(date) { + return DateFormat('MMM dd, yyy, kk:mm').format(date); + } + + authenticateUser(type, isActive, authProv) { + //GifLoaderDialogUtils.showMyDialog(context); + // if (type == 2 || type == 3) { + // fingrePrintBefore = type; + // } + //this.selectedOption = fingrePrintBefore != null ? fingrePrintBefore : type; + + switch (type) { + case 1: + this.loginWithSMS(1, isActive, authProv); + break; + case 2: + this.loginWithSMS(2, isActive, authProv); + + break; + case 3: + this.loginWithFingurePrintFace(3, isActive, authProv); + break; + case 4: + this.loginWithFingurePrintFace(4, isActive, authProv); + break; + default: + break; + } + // sharedPref.setInt(LAST_LOGIN, + // this.selectedOption); //this.cs.sharedService.setStorage(this.selectedOption, AuthenticationService.LAST_LOGIN); + } + + loginWithSMS(type, isActive, authProv) { + this.sendActivationCode(type, authProv); + // //if (!el.disabled) { + // if (this.user != null) { + // this.checkUserAuthentication(type); + // } else { + // // if (this.loginTokenID != null) { + // this.sendActivationCode(type, authProv); + // // } else { + // //this.checkUserAuthentication(type); + // // } + // } + } + + // checkUserAuthentication(type) { + // // showLoader(true); + // // var req = getCommonRequest(type: type); + // // req.logInTokenID = ""; + + // // var request = CheckPatientAuthenticationReq.fromJson(req.toJson()); + + // // sharedPref.setObject(REGISTER_DATA_FOR_REGISTER, request); + // // authService + // // .checkPatientAuthentication(request) + // // .then((value) => { + // // GifLoaderDialogUtils.hideDialog(context), + // // if (value['isSMSSent']) + // // { + // // sharedPref.setString(LOGIN_TOKEN_ID, value['LogInTokenID']), + // // this.loginTokenID = value['LogInTokenID'], + // // sharedPref.setObject(REGISTER_DATA_FOR_LOGIIN, request), + // // // Future.delayed(Duration(seconds: 1), () { + // // this.sendActivationCode(type) + // // // }) + // // } + // // else + // // { + // // if (value['IsAuthenticated']) {this.checkActivationCode()} + // // } + // // }) + // // .catchError((err) { + // // print(err); + // // GifLoaderDialogUtils.hideDialog(context); + // // }); + // } + Future _getAvailableBiometrics() async { + var availableBiometrics; + try { + availableBiometrics = await auth.getAvailableBiometrics(); + } on PlatformException catch (e) { + print(e); + } + if (!mounted) return; + + setState(() { + _availableBiometrics = availableBiometrics; + }); + } + + sendActivationCode(type, authProv) async { + if (user != null) { + sendActivationCodeVerificationScreen(type, authProv); + } else { + sendActivationCodeByOtpNotificationType(type, authProv); + } + } + + startSMSService(type, authProv) { + sharedPref.setInt(OTP_TYPE, type); + new SMSOTP( + context, + type, + _loggedUser['MobileNumber'], + (value) { + showDialog( + context: context, + builder: (BuildContext context) { + return Center( + child: CircularProgressIndicator(), + ); + }); + + this.checkActivationCode(authProv, value: value); + }, + () => { + Navigator.pop(context), + print('Faild..'), + }, + ).displayDialog(context); + } + + loginWithFingurePrintFace(type, isActive, authProv) async { + if (isActive == 1) { + // this.startBiometricLoginIfAvailable(); + authenticated = await auth.authenticateWithBiometrics( + localizedReason: 'Scan your fingerprint to authenticate', + useErrorDialogs: true, + stickyAuth: true); + if (user.logInTypeID == 1 || user.logInTypeID == 2) { + this.onlySMSBox = true; + } else { + this.checkActivationCode(authProv); + } + + // if (authenticated == true) { + // if (user != null && (user.logInTypeID == 4 || user.logInTypeID == 3)) { + // //this.checkActivationCode(); + // } else { + // // var request = this.getCommonRequest(type: type); + // // this.getMobileInfo(request); + // } + // } + } + } + + checkActivationCode(AuthViewModel authProv, {value}) async { + CheckActivationCodeRequestModel checkActivationCodeForDoctorApp = + new CheckActivationCodeRequestModel( + zipCode: _loggedUser['ZipCode'], + mobileNumber: _loggedUser['MobileNumber'], + projectID: await sharedPref.getInt(PROJECT_ID), + logInTokenID: await sharedPref.getString(LOGIN_TOKEN_ID), + activationCode: value, + oTPSendType: await sharedPref.getInt(OTP_TYPE), + generalid: "Cs2020@2016\$2958"); + + authProv + .checkActivationCodeForDoctorApp(checkActivationCodeForDoctorApp) + .then((res) async { + widget.changeLoadingStata(false); + if (res['MessageStatus'] == 1) { + sharedPref.setString(TOKEN, res['AuthenticationTokenID']); + if (res['List_DoctorProfile'] != null) { + loginProcessCompleted(res['List_DoctorProfile'][0], authProv); + } else { + ClinicModel clinic = + ClinicModel.fromJson(res['List_DoctorsClinic'][0]); + getDocProfiles(clinic, authProv); + } + } else { + //changeLoadingStata(false); + helpers.showErrorToast(res['ErrorEndUserMessage']); + } + }).catchError((err) { + //changeLoadingStata(false); + helpers.showErrorToast(err); + }); + } + + loginProcessCompleted(Map profile, authProv) { + var doctor = DoctorProfileModel.fromJson(profile); + authProv.setDoctorProfile(doctor); + sharedPref.setObj(DOCTOR_PROFILE, profile); + projectsProvider.isLogin = true; + Navigator.of(context).pushReplacementNamed(HOME); + } + + getDocProfiles(ClinicModel clinicInfo, authProv) { + ProfileReqModel docInfo = new ProfileReqModel( + doctorID: clinicInfo.doctorID, + clinicID: clinicInfo.clinicID, + license: true, + projectID: clinicInfo.projectID, + tokenID: '', + languageID: 2); + authProv.getDocProfiles(docInfo.toJson()).then((res) { + if (res['MessageStatus'] == 1) { + loginProcessCompleted(res['DoctorProfileList'][0], authProv); + } else { + // changeLoadingStata(false); + helpers.showErrorToast(res['ErrorEndUserMessage']); + } + }).catchError((err) { + // changeLoadingStata(false); + helpers.showErrorToast(err); + }); + } } diff --git a/lib/widgets/charts/app_bar_chart.dart b/lib/widgets/charts/app_bar_chart.dart new file mode 100644 index 00000000..98ef3cfa --- /dev/null +++ b/lib/widgets/charts/app_bar_chart.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; +import 'package:charts_flutter/flutter.dart' as charts; + +class AppBarChart extends StatelessWidget { + const AppBarChart({ + Key key, + @required this.seriesList, + }) : super(key: key); + + final List seriesList; + + @override + Widget build(BuildContext context) { + return Container( + height: 400, + margin: EdgeInsets.only(top: 60), + child: charts.BarChart( + seriesList, + // animate: animate, + + /// Customize the primary measure axis using a small tick renderer. + /// Use String instead of num for ordinal domain axis + /// (typically bar charts). + primaryMeasureAxis: new charts.NumericAxisSpec( + renderSpec: new charts.GridlineRendererSpec( + // Display the measure axis labels below the gridline. + // + // 'Before' & 'after' follow the axis value direction. + // Vertical axes draw 'before' below & 'after' above the tick. + // Horizontal axes draw 'before' left & 'after' right the tick. + labelAnchor: charts.TickLabelAnchor.before, + + // Left justify the text in the axis. + // + // Note: outside means that the secondary measure axis would right + // justify. + labelJustification: + charts.TickLabelJustification.outside, + )), + ), + ); + } +} diff --git a/lib/widgets/charts/app_line_chart.dart b/lib/widgets/charts/app_line_chart.dart new file mode 100644 index 00000000..553afec8 --- /dev/null +++ b/lib/widgets/charts/app_line_chart.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import 'package:charts_flutter/flutter.dart' as charts; + +/// chart line +/// [seriesList] charts series +/// [chartTitle] the charts title +/// [animate] enable and disable animate on create chart +/// [includeArea] chart include Area +/// [stacked] stacked chart over the design +class AppLineChart extends StatelessWidget { + final List seriesList; + final String chartTitle; + final bool animate; + final bool includeArea; + final bool stacked; + + AppLineChart( + {Key key, + @required this.seriesList, + this.chartTitle, + this.animate = true, + this.includeArea = false, + this.stacked = true}); + + @override + Widget build(BuildContext context) { + return Container( + child: Column( + children: [ + Text( + chartTitle, + style: TextStyle(fontSize: 24.0, fontWeight: FontWeight.bold), + ), + Expanded( + child: charts.LineChart(seriesList, + defaultRenderer: charts.LineRendererConfig( + includeArea: false, stacked: true), + animate: animate), + ), + ], + ), + ); + } +} diff --git a/lib/widgets/charts/app_time_series_chart.dart b/lib/widgets/charts/app_time_series_chart.dart new file mode 100644 index 00000000..670284a1 --- /dev/null +++ b/lib/widgets/charts/app_time_series_chart.dart @@ -0,0 +1,71 @@ +import 'package:charts_flutter/flutter.dart' as charts; +import 'package:charts_flutter/flutter.dart'; +import 'package:doctor_app_flutter/config/size_config.dart'; +import 'package:doctor_app_flutter/widgets/data_display/list/flexible_container.dart'; +import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; +import 'package:flutter/material.dart'; + +/// App Time Series Chart +/// [seriesList] the series list +/// [chartName] the name of the chart +/// [startDate] the start date +/// [endDate] the end date +class AppTimeSeriesChart extends StatelessWidget { + AppTimeSeriesChart({ + Key key, + @required this.seriesList, + this.chartName = '', + this.startDate, + this.endDate, + }); + + final String chartName; + final List> seriesList; + final DateTime startDate; + final DateTime endDate; + + @override + Widget build(BuildContext context) { + return FlexibleContainer( + heightFactor: 0.47, + child: Column( + children: [ + AppText(chartName, fontSize: SizeConfig.textMultiplier * 3), + Container( + height: SizeConfig.realScreenHeight * 0.37, + child: Center( + child: Container( + child: charts.TimeSeriesChart( + seriesList, + animate: true, + behaviors: [ + charts.RangeAnnotation( + [ + charts.RangeAnnotationSegment(startDate, endDate, + charts.RangeAnnotationAxisType.domain ), + ], + ), + ], + ), + ), + ), + ), + ], + ), + ); + } +} + +class TimeSeriesSales { + final DateTime time; + final int sales; + + TimeSeriesSales(this.time, this.sales); +} + +class TimeSeriesSales2 { + final DateTime time; + final double sales; + + TimeSeriesSales2(this.time, this.sales); +} diff --git a/lib/widgets/data_display/list/custom_Item.dart b/lib/widgets/data_display/list/custom_Item.dart new file mode 100644 index 00000000..c11af999 --- /dev/null +++ b/lib/widgets/data_display/list/custom_Item.dart @@ -0,0 +1,93 @@ +import 'package:eva_icons_flutter/eva_icons_flutter.dart'; +import 'package:flutter/material.dart'; + +/// Custom Item widget +/// [startIcon] icon at the start of the widget +/// [startIconSize] icon size of start icon +/// [startIconColor] icon color of start icon +/// [endIcon] icon at the end of the widget +/// [endIconSize] icon size of end icon +/// [endIconColor] icon color of end icon +/// [disabled] disabled on tap function +/// [onTap] opTap function +/// [padding] padding of the widget +/// [child] child of the widget +/// [decoration] decoration of the widget +class CustomItem extends StatelessWidget { + final IconData startIcon; + final double startIconSize; + final Color startIconColor; + final IconData endIcon; + final double endIconSize; + final Color endIconColor; + final bool disabled; + final Function onTap; + final EdgeInsets padding; + final Widget child; + final BoxDecoration decoration; + + CustomItem( + {Key key, + this.startIcon, + this.disabled: false, + this.onTap, + this.startIconColor, + this.endIcon = EvaIcons.chevronRight, + this.padding, + this.child, + this.endIconColor, + this.endIconSize = 20, + this.decoration, + this.startIconSize = 19}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return IgnorePointer( + ignoring: disabled, + child: Container( + decoration: decoration != null ? decoration : BoxDecoration(), + child: InkWell( + onTap: () { + if (onTap != null) onTap(); + }, + child: Padding( + padding: padding != null + ? padding + : const EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0), + child: Row( + children: [ + if (startIcon != null) + Expanded( + flex: 1, + child: Icon( + startIcon, + color: startIconColor ?? Theme.of(context).primaryColor, + size: startIconSize, + ), + ), + if (startIcon != null) SizedBox(width: 18.0), + Expanded( + child: child, + flex: 10, + ), + endIcon == null + ? Expanded(child: Container()) + : Expanded( + flex: 1, + child: Icon( + endIcon, + color: endIconColor != null + ? endIconColor + : Colors.grey[500], + size: endIconSize, + ), + ) + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/widgets/data_display/list/flexible_container.dart b/lib/widgets/data_display/list/flexible_container.dart new file mode 100644 index 00000000..a35fa279 --- /dev/null +++ b/lib/widgets/data_display/list/flexible_container.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +/// Flexible container widget +/// [widthFactor] If non-null, the fraction of the incoming width given to the child. +/// If non-null, the child is given a tight width constraint that is the max +/// incoming width constraint multiplied by this factor. +/// If null, the incoming width constraints are passed to the child + +/// [heightFactor]If non-null, the fraction of the incoming height given to the child. +/// If non-null, the child is given a tight height constraint that is the max +/// incoming height constraint multiplied by this factor. +/// If null, the incoming height constraints are passed to the child +/// [padding] add padding to the container +/// [child] child widget inside the container +class FlexibleContainer extends StatelessWidget { + final double widthFactor; + final double heightFactor; + final EdgeInsets padding; + final Widget child; + + FlexibleContainer({ + Key key, + this.widthFactor = 0.9, + this.heightFactor = 1, + this.padding, + this.child, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( +// widthFactor: widthFactor, +// heightFactor: heightFactor, + child: ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: Material( + color: Theme.of(context).backgroundColor, + child: Container( + padding: padding, + width: double.infinity, + decoration: BoxDecoration( + border: Border.all( + color: Theme.of(context).dividerColor, width: 2.0), + borderRadius: BorderRadius.circular(8.0)), + child: child, + ), + ), + ), + ); + } +} diff --git a/lib/widgets/otp/sms-popup.dart b/lib/widgets/otp/sms-popup.dart new file mode 100644 index 00000000..dfcb33cd --- /dev/null +++ b/lib/widgets/otp/sms-popup.dart @@ -0,0 +1,346 @@ +import 'dart:async'; + +import 'package:doctor_app_flutter/config/size_config.dart'; +import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; +import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; +import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; +import 'package:flutter/material.dart'; +import 'dart:math'; + +import 'package:provider/provider.dart'; + +class SMSOTP { + final type; + final mobileNo; + final Function onSuccess; + final Function onFailure; + final context; + + int remainingTime = 600; + + Future timer; + + static BuildContext _context; + + static bool _loading; + + SMSOTP( + this.context, + this.type, + this.mobileNo, + this.onSuccess, + this.onFailure, + ); + + final verifyAccountForm = GlobalKey(); + + TextEditingController digit1 = TextEditingController(text: ""); + TextEditingController digit2 = TextEditingController(text: ""); + TextEditingController digit3 = TextEditingController(text: ""); + TextEditingController digit4 = TextEditingController(text: ""); + + Map verifyAccountFormValue = { + 'digit1': '', + 'digit2': '', + 'digit3': '', + 'digit4': '', + }; + final focusD1 = FocusNode(); + final focusD2 = FocusNode(); + final focusD3 = FocusNode(); + final focusD4 = FocusNode(); + String errorMsg; + ProjectViewModel projectProvider; + String displayTime = ''; + + displayDialog(BuildContext context) async { + return showDialog( + context: context, + builder: (context) { + projectProvider = Provider.of(context); + return AlertDialog( + title: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + IconButton( + icon: Icon(Icons.close), + onPressed: () { + Navigator.pop(context); + this.onFailure(); + }, + ) + ], + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(10.0))), + content: StatefulBuilder(builder: (context, setState) { + if (displayTime == '') { + startTimer(setState); + } + return Container( + color: Colors.white, + height: SizeConfig.realScreenHeight * 0.5, + width: SizeConfig.realScreenWidth * 0.8, + child: Center( + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + type == 1 + ? Image.asset('assets/images/login/103.png') + : Image.asset('assets/images/login/104.png'), + Padding( + padding: EdgeInsets.only(top: 5), + child: AppText( + TranslationBase.of(context).verificationMessage + + ' XXXXXX' + + mobileNo + .toString() + .substring(mobileNo.toString().length - 3), + textAlign: TextAlign.center, + )), + Form( + key: verifyAccountForm, + child: Padding( + padding: EdgeInsets.only(top: 20), + child: Directionality( + textDirection: TextDirection.ltr, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Container( + width: SizeConfig.realScreenWidth * 0.15, + child: TextFormField( + textInputAction: TextInputAction.next, + style: buildTextStyle(), + autofocus: true, + maxLength: 1, + controller: digit1, + textAlign: TextAlign.center, + keyboardType: TextInputType.number, + decoration: buildInputDecoration(context), + onSaved: (val) {}, + validator: validateCodeDigit, + onFieldSubmitted: (_) { + FocusScope.of(context) + .requestFocus(focusD2); + }, + onChanged: (val) { + if (val.length == 1) { + FocusScope.of(context) + .requestFocus(focusD2); + verifyAccountFormValue['digit1'] = + val.trim(); + checkValue(); + } + }, + ), + ), + Container( + width: SizeConfig.realScreenWidth * 0.15, + child: TextFormField( + focusNode: focusD2, + textInputAction: TextInputAction.next, + maxLength: 1, + controller: digit2, + textAlign: TextAlign.center, + style: buildTextStyle(), + keyboardType: TextInputType.number, + decoration: buildInputDecoration(context), + onSaved: (val) {}, + onFieldSubmitted: (_) { + FocusScope.of(context) + .requestFocus(focusD3); + }, + onChanged: (val) { + if (val.length == 1) { + FocusScope.of(context) + .requestFocus(focusD3); + verifyAccountFormValue['digit2'] = + val.trim(); + checkValue(); + } + }, + validator: validateCodeDigit), + ), + Container( + width: SizeConfig.realScreenWidth * 0.15, + child: TextFormField( + focusNode: focusD3, + textInputAction: TextInputAction.next, + maxLength: 1, + controller: digit3, + textAlign: TextAlign.center, + style: buildTextStyle(), + keyboardType: TextInputType.number, + decoration: + buildInputDecoration(context), + onSaved: (val) {}, + onFieldSubmitted: (_) { + FocusScope.of(context) + .requestFocus(focusD4); + }, + onChanged: (val) { + if (val.length == 1) { + FocusScope.of(context) + .requestFocus(focusD4); + verifyAccountFormValue['digit3'] = + val.trim(); + checkValue(); + } + }, + validator: validateCodeDigit)), + Container( + width: SizeConfig.realScreenWidth * 0.15, + child: TextFormField( + focusNode: focusD4, + maxLength: 1, + textAlign: TextAlign.center, + style: buildTextStyle(), + controller: digit4, + keyboardType: TextInputType.number, + decoration: + buildInputDecoration(context), + onFieldSubmitted: (_) { + FocusScope.of(context) + .requestFocus(focusD4); + }, + onChanged: (val) { + if (val.length == 1) { + verifyAccountFormValue['digit4'] = + val.trim(); + checkValue(); + } + }, + validator: validateCodeDigit)), + ], + )), + ), + ), + Padding( + padding: EdgeInsets.only(top: 10), + child: AppText( + TranslationBase.of(context).validationMessage + + ' ' + + displayTime, + color: Colors.red, + textAlign: TextAlign.center, + )) + ], + ))), + ); + }), + ); + }); + } + + TextStyle buildTextStyle() { + return TextStyle( + fontSize: SizeConfig.textMultiplier * 3, + ); + } + + InputDecoration buildInputDecoration(BuildContext context) { + return InputDecoration( + counterText: " ", + // ts/images/password_icon.png + // contentPadding: EdgeInsets.only(top: 20, bottom: 20), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(10)), + borderSide: BorderSide(color: Colors.black), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(10.0)), + borderSide: BorderSide(color: Theme.of(context).primaryColor), + ), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(10.0)), + borderSide: BorderSide(color: Theme.of(context).errorColor), + ), + focusedErrorBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(10.0)), + borderSide: BorderSide(color: Theme.of(context).errorColor), + ), + ); + } + + String validateCodeDigit(value) { + if (value.isEmpty) { + return ' '; + } else if (value.length == 3) { + print(value); + } else { + return null; + } + } + + checkValue() { + //print(verifyAccountFormValue); + if (verifyAccountForm.currentState.validate()) { + onSuccess(digit1.text.toString() + + digit2.text.toString() + + digit3.text.toString() + + digit4.text.toString()); + } + } + + getSecondsAsDigitalClock(int inputSeconds) { + var sec_num = + int.parse(inputSeconds.toString()); // don't forget the second param + var hours = (sec_num / 3600).floor(); + var minutes = ((sec_num - hours * 3600) / 60).floor(); + var seconds = sec_num - hours * 3600 - minutes * 60; + var minutesString = ""; + var secondsString = ""; + minutesString = + minutes < 10 ? "0" + minutes.toString() : minutes.toString(); + secondsString = + seconds < 10 ? "0" + seconds.toString() : seconds.toString(); + return minutesString + ":" + secondsString; + } + + startTimer(setState) { + this.remainingTime--; + setState(() { + displayTime = this.getSecondsAsDigitalClock(this.remainingTime); + }); + + timer = Future.delayed(Duration(seconds: 1), () { + if (this.remainingTime > 0) { + startTimer(setState); + } else { + Navigator.pop(context); + } + }); + } + + static void showLoadingDialog(BuildContext context, bool _loading) async { + _context = context; + + if (_loading == false) { + Navigator.of(context).pop(); + return; + } + _loading = true; + await showDialog( + context: _context, + barrierDismissible: false, + builder: (BuildContext context) { + return SimpleDialog( + elevation: 0.0, + backgroundColor: Colors.transparent, + children: [ + Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(Colors.black), + ), + ) + ], + ); + }); + } + + static void hideSMSBox(context) { + Navigator.pop(context); + } +} diff --git a/lib/widgets/patients/dynamic_elements.dart b/lib/widgets/patients/dynamic_elements.dart index 25d196d0..e6688397 100644 --- a/lib/widgets/patients/dynamic_elements.dart +++ b/lib/widgets/patients/dynamic_elements.dart @@ -59,22 +59,49 @@ class _DynamicElementsState extends State { @override Widget build(BuildContext context) { + final screenSize = MediaQuery + .of(context) + .size; + InputDecoration textFieldSelectorDecoration({String hintText, + String selectedText, bool isDropDown,IconData icon}) { + return InputDecoration( + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: Color(0xFFCCCCCC), width: 2.0), + borderRadius: BorderRadius.circular(8), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: Color(0xFFCCCCCC), width: 2.0), + borderRadius: BorderRadius.circular(8), + ), + disabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: Color(0xFFCCCCCC), width: 2.0), + borderRadius: BorderRadius.circular(8), + ), + hintText: selectedText != null ? selectedText : hintText, + suffixIcon: isDropDown ? Icon(icon ?? Icons.arrow_drop_down) : null, + hintStyle: TextStyle( + fontSize: 14, + color: Colors.grey.shade600, + ), + ) + ; + } return LayoutBuilder( builder: (ctx, constraints) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + SizedBox( + height: 10, + ), SizedBox( height: 10, ), AppTextFormField( - textInputType: TextInputType.number, + onTap: ()=> _presentDatePicker('_selectedFromDate'), hintText: TranslationBase.of(context).fromDate, controller: _fromDateController, inputFormatter: ONLY_DATE, - onTap: () { - _presentDatePicker('_selectedFromDate'); - }, onSaved: (value) { if (_fromDateController.text.toString().trim().isEmpty) { widget._patientSearchFormValues.From = "0"; @@ -82,12 +109,14 @@ class _DynamicElementsState extends State { widget._patientSearchFormValues.From = _fromDateController.text.replaceAll("/", "-"); } }, + readOnly: true, + ), SizedBox( height: 10, ), AppTextFormField( - textInputType: TextInputType.number, + readOnly: true, hintText: TranslationBase .of(context) .toDate, diff --git a/lib/widgets/patients/patient-referral-item-widget.dart b/lib/widgets/patients/patient-referral-item-widget.dart index 662e7fee..17f33793 100644 --- a/lib/widgets/patients/patient-referral-item-widget.dart +++ b/lib/widgets/patients/patient-referral-item-widget.dart @@ -37,7 +37,7 @@ class PatientReferralItemWidget extends StatelessWidget { children: [ Center( child: AppText( - patientName, + "${patientName}", color: Colors.black, fontWeight: FontWeight.bold, fontSize: 16, @@ -48,9 +48,10 @@ class PatientReferralItemWidget extends StatelessWidget { color: Color(0xFF4BA821), padding: EdgeInsets.all(4), child: AppText( - referralStatus == "46" + referralStatus + /*referralStatus == "46" ? TranslationBase.of(context).approved - : TranslationBase.of(context).rejected, + : TranslationBase.of(context).rejected*/, color: Colors.white, fontWeight: FontWeight.bold, fontSize: 12, diff --git a/lib/widgets/patients/profile/patient-page-header-widget.dart b/lib/widgets/patients/profile/patient-page-header-widget.dart index 3e870be5..a6c47a7f 100644 --- a/lib/widgets/patients/profile/patient-page-header-widget.dart +++ b/lib/widgets/patients/profile/patient-page-header-widget.dart @@ -1,92 +1,109 @@ +import 'package:doctor_app_flutter/core/viewModel/SOAP_view_model.dart'; import 'package:doctor_app_flutter/icons_app/doctor_app_icons.dart'; +import 'package:doctor_app_flutter/models/SOAP/GeneralGetReqForSOAP.dart'; import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart'; +import 'package:doctor_app_flutter/screens/base/base_view.dart'; import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; import 'package:doctor_app_flutter/widgets/patients/profile/patient_profile_widget.dart'; import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; +import 'package:doctor_app_flutter/widgets/shared/network_base_view.dart'; import 'package:flutter/material.dart'; class PatientPageHeaderWidget extends StatelessWidget { final PatiantInformtion patient; - PatientPageHeaderWidget(this.patient); @override Widget build(BuildContext context) { - return Container( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - AvatarWidget( - Icon( - patient.genderDescription == "Male" - ? DoctorApp.male - : DoctorApp.female_icon, - size: 70, - color: Colors.white, - ), - ), - SizedBox( - width: 20, - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - SizedBox( - height: 5, - ), - AppText( - patient.firstName + ' ' + patient.lastName, - color: Colors.black, - fontWeight: FontWeight.bold, - ), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AppText( - TranslationBase.of(context).age, - color: Colors.black, - fontWeight: FontWeight.bold, - ), - SizedBox( - width: 20, + return BaseView( + onModelReady: (model) async { + GeneralGetReqForSOAP generalGetReqForSOAP = GeneralGetReqForSOAP( + patientMRN: patient.patientMRN, + episodeId: patient.episodeNo, + appointmentNo: patient.appointmentNo, + doctorID: '', + editedBy: ''); + await model.getPatientAllergy(generalGetReqForSOAP); + + }, + builder: (_, model, w) => Container( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + AvatarWidget( + Icon( + patient.genderDescription == "Male" + ? DoctorApp.male + : DoctorApp.female_icon, + size: 70, + color: Colors.white, ), - AppText( - patient.age.toString(), - color: Colors.black, - fontWeight: FontWeight.normal, + ), + SizedBox( + width: 20, + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox( + height: 5, + ), + AppText( + patient.firstName + ' ' + patient.lastName, + color: Colors.black, + fontWeight: FontWeight.bold, + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AppText( + TranslationBase.of(context).age, + color: Colors.black, + fontWeight: FontWeight.bold, + ), + SizedBox( + width: 20, + ), + AppText( + patient.age.toString(), + color: Colors.black, + fontWeight: FontWeight.normal, + ), + ], + ), + NetworkBaseView( + baseViewModel: model, + child: model.patientAllergiesList.isNotEmpty ?AppText( + "ALLERGIC TO: "+model.getAllergicNames(), + color: Color(0xFFB9382C), + fontWeight: FontWeight.bold, + ) : AppText(''), + ), + ], ), - ], - ), - AppText( - "ALLERGIC TO: FOOD, ASPIRIN, EGG WHITE", - color: Color(0xFFB9382C), - fontWeight: FontWeight.bold, - ), - ], + ) + ], + ), + ), + Container( + width: double.infinity, + height: 1, + color: Color(0xffCCCCCC), + ), + SizedBox( + width: 20, ), - ) - ], - ), - ), - Container( - width: double.infinity, - height: 1, - color: Color(0xffCCCCCC), - ), - SizedBox( - width: 20, - ), - ], - ), - ); + ], + ), + )); } } diff --git a/lib/widgets/patients/profile/patient_profile_widget.dart b/lib/widgets/patients/profile/patient_profile_widget.dart index 7f49c868..04e090f1 100644 --- a/lib/widgets/patients/profile/patient_profile_widget.dart +++ b/lib/widgets/patients/profile/patient_profile_widget.dart @@ -23,6 +23,8 @@ class PatientProfileWidget extends StatelessWidget { final routeArgs = ModalRoute.of(context).settings.arguments as Map; patient = routeArgs['patient']; String patientType = routeArgs['patientType']; + String from = routeArgs['from']; + String to = routeArgs['to']; return Container( color: Color(0XFFF2F2F2), @@ -442,7 +444,7 @@ class PatientProfileWidget extends StatelessWidget { SliverPadding( padding: const EdgeInsets.all(16.0), sliver: ProfileMedicalInfoWidget( - patient: patient, patientType:patientType + patient: patient, patientType:patientType, from: from, to: to, )) ]), ); diff --git a/lib/widgets/patients/profile/profile_medical_info_widget.dart b/lib/widgets/patients/profile/profile_medical_info_widget.dart index 5c26a39a..ad813be0 100644 --- a/lib/widgets/patients/profile/profile_medical_info_widget.dart +++ b/lib/widgets/patients/profile/profile_medical_info_widget.dart @@ -1,7 +1,14 @@ import 'package:doctor_app_flutter/config/config.dart'; +import 'package:doctor_app_flutter/core/enum/viewstate.dart'; +import 'package:doctor_app_flutter/core/viewModel/SOAP_view_model.dart'; +import 'package:doctor_app_flutter/models/SOAP/PostEpisodeReqModel.dart'; import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart'; import 'package:doctor_app_flutter/routes.dart'; +import 'package:doctor_app_flutter/screens/base/base_view.dart'; +import 'package:doctor_app_flutter/util/date-utils.dart'; import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; +import 'package:doctor_app_flutter/widgets/shared/dr_app_circular_progress_Indeicator.dart'; +import 'package:doctor_app_flutter/widgets/shared/network_base_view.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:hexcolor/hexcolor.dart'; @@ -17,12 +24,16 @@ import '../../shared/app_texts_widget.dart'; *@desc: Profile Medical Info Widget */ class ProfileMedicalInfoWidget extends StatelessWidget { - ProfileMedicalInfoWidget({Key key, this.patient, this.patientType}); + ProfileMedicalInfoWidget( + {Key key, this.patient, this.patientType, this.from, this.to}); + PatiantInformtion patient; - String patientType; + String patientType; @override Widget build(BuildContext context) { - return SliverGrid.count( + return BaseView( + onModelReady: (model) async {}, + builder: (_, model, w) => SliverGrid.count( crossAxisSpacing: 10, mainAxisSpacing: 20, crossAxisCount: 2, @@ -32,26 +43,36 @@ class ProfileMedicalInfoWidget extends StatelessWidget { PatientProfileButton( key: key, patient: patient, - nameLine1: TranslationBase.of(context).createNew, + isDisable: patient.episodeNo != 0 ? true : false,nameLine1: TranslationBase.of(context).createNew, nameLine2: TranslationBase.of(context).episode, route: CREATE_EPISODE, - icon: 'create-episod.png'), + onTap: () async { + PostEpisodeReqModel postEpisodeReqModel = PostEpisodeReqModel( + appointmentNo: patient.appointmentNo, + patientMRN: patient.patientMRN); + await model.postEpisode(postEpisodeReqModel); + patient.episodeNo = model.episodeID; + Navigator.of(context).pushNamed(CREATE_EPISODE, + arguments: {'patient': patient}); + }, + isLoading: model.state == ViewState.BusyLocal,icon: 'create-episod.png'), if (int.parse(patientType) == 7) PatientProfileButton( key: key, patient: patient, - nameLine1: TranslationBase.of(context).update, + isDisable: patient.episodeNo == 0 ? true : false,nameLine1: TranslationBase.of(context).update, nameLine2: TranslationBase.of(context).episode, route: UPDATE_EPISODE, - icon: 'modilfy-episode.png'), - PatientProfileButton( - key: key, - patient: patient, - nameLine1: TranslationBase.of(context).vital, - nameLine2: TranslationBase.of(context).signs, - route: (selectedPatientType == 6 || selectedPatientType == 7) - ? PATIENT_VITAL_SIGN - : VITAL_SIGN_DETAILS, + icon: 'modilfy-episode.png'),if (int.parse(patientType) == 7) + PatientProfileButton( + key: key, + patient: patient, + from: from, + to: to, + nameLine1: TranslationBase.of(context).vital, + nameLine2: TranslationBase.of(context).signs, + route: VITAL_SIGN_DETAILS /* PATIENT_VITAL_SIGN + */, icon: 'heartbeat.png'), if (selectedPatientType != 7) PatientProfileButton( @@ -68,7 +89,9 @@ class ProfileMedicalInfoWidget extends StatelessWidget { nameLine1: TranslationBase.of(context).previewHealth, nameLine2: TranslationBase.of(context).summaryReport, icon: 'radiology-1.png'), - if (selectedPatientType != 0 && selectedPatientType != 5) + if (selectedPatientType != 0 && + selectedPatientType != 5 && + selectedPatientType != 7) PatientProfileButton( key: key, patient: patient, @@ -130,7 +153,9 @@ class ProfileMedicalInfoWidget extends StatelessWidget { nameLine1: TranslationBase.of(context).patient, nameLine2: TranslationBase.of(context).ucaf, icon: 'lab.png'), - ]); + ], + ), + ); } } @@ -189,23 +214,39 @@ class PatientProfileButton extends StatelessWidget { final String icon; final dynamic route; final PatiantInformtion patient; + String from; + String to; final String url = "assets/images/"; + final bool isDisable; + final bool isLoading; + final Function onTap; + PatientProfileButton( {Key key, this.patient, this.nameLine1, this.nameLine2, this.icon, - this.route}) + this.route, + this.isDisable = false, + this.onTap, + this.isLoading = false, + this.from, + this.to}) : super(key: key); + @override Widget build(BuildContext context) { return new Container( margin: new EdgeInsets.symmetric(horizontal: 4.0), child: InkWell( - onTap: () { - navigator(context, this.route); - }, + onTap: isDisable + ? null + : onTap != null + ? onTap + : () { + navigator(context, this.route); + }, child: Column(children: [ Container( alignment: Alignment.topLeft, @@ -227,6 +268,7 @@ class PatientProfileButton extends StatelessWidget { textAlign: TextAlign.left, fontSize: SizeConfig.textMultiplier * 2, ), + if (isLoading) DrAppCircularProgressIndeicator() ], ), ), @@ -245,7 +287,7 @@ class PatientProfileButton extends StatelessWidget { ), decoration: BoxDecoration( // border: Border.all(), - color: Colors.white, + color: isDisable ? Colors.grey.withOpacity(0.4) : Colors.white, borderRadius: BorderRadius.all(Radius.circular(10)), border: Border.fromBorderSide(BorderSide( color: Color(0xffBBBBBB), @@ -265,6 +307,13 @@ class PatientProfileButton extends StatelessWidget { } void navigator(BuildContext context, route) { - Navigator.of(context).pushNamed(route, arguments: {'patient': patient}); + if (from == null) { + from = DateUtils.convertDateToFormat(DateTime.now(), 'yyyy-MM-dd'); + } + if (to == null) { + to = DateUtils.convertDateToFormat(DateTime.now(), 'yyyy-MM-dd'); + } + Navigator.of(context).pushNamed(route, + arguments: {'patient': patient, 'from': from, 'to': to}); } } diff --git a/lib/widgets/patients/profile/soap_update/custom_validation_error.dart b/lib/widgets/patients/profile/soap_update/custom_validation_error.dart new file mode 100644 index 00000000..a05d52a2 --- /dev/null +++ b/lib/widgets/patients/profile/soap_update/custom_validation_error.dart @@ -0,0 +1,33 @@ + +import 'package:doctor_app_flutter/util/translations_delegate_base.dart'; +import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; +import 'package:flutter/material.dart'; + +// ignore: must_be_immutable +class CustomValidationError extends StatelessWidget { + String error; + CustomValidationError({ + Key key, this.error, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + if(error == null ) + error = TranslationBase + .of(context) + .emptyMessage; + return Column( + children: [ + SizedBox( + height: 2, + ), + Container( + margin: EdgeInsets.symmetric(horizontal: 3), + child: AppText(error, color: Theme + .of(context) + .errorColor, fontSize: 14,), + ), + ], + ); + } +} \ No newline at end of file diff --git a/lib/widgets/patients/profile/soap_update/subjective/update_allergies_widget.dart b/lib/widgets/patients/profile/soap_update/subjective/update_allergies_widget.dart index 6de9e031..38a0896b 100644 --- a/lib/widgets/patients/profile/soap_update/subjective/update_allergies_widget.dart +++ b/lib/widgets/patients/profile/soap_update/subjective/update_allergies_widget.dart @@ -19,6 +19,8 @@ import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:provider/provider.dart'; +import '../custom_validation_error.dart'; + class UpdateAllergiesWidget extends StatefulWidget { final List myAllergiesList; @@ -226,10 +228,11 @@ class _AddAllergiesState extends State { MasterKeyModel _selectedAllergy; TextEditingController remarkController = TextEditingController(); GlobalKey key = new GlobalKey>(); + bool isFormSubmitted = false; - - InputDecoration textFieldSelectorDecoration(String hintText, - String selectedText, bool isDropDown,{IconData icon}) { + InputDecoration textFieldSelectorDecoration( + String hintText, String selectedText, bool isDropDown, + {IconData icon}) { return InputDecoration( focusedBorder: OutlineInputBorder( borderSide: BorderSide(color: Color(0xFFCCCCCC), width: 2.0), @@ -328,18 +331,24 @@ class _AddAllergiesState extends State { input.toLowerCase()) || suggestion.nameEn.toLowerCase() .startsWith(input.toLowerCase()), - ):TextField( + ) : TextField( decoration: textFieldSelectorDecoration( TranslationBase .of(context) .selectAllergy, _selectedAllergy != null - ? projectViewModel.isArabic?_selectedAllergy.nameAr: _selectedAllergy.nameEn - : null, true, icon: EvaIcons.search), + ? projectViewModel.isArabic + ? _selectedAllergy.nameAr + : _selectedAllergy.nameEn + : null, + true, + icon: EvaIcons.search), enabled: false, ), ), ), + if(isFormSubmitted && _selectedAllergy == null) + CustomValidationError(), SizedBox( height: 10, ), @@ -382,6 +391,8 @@ class _AddAllergiesState extends State { ), ), ), + if(isFormSubmitted && _selectedAllergySeverity == null) + CustomValidationError(), SizedBox( height: 10, ), @@ -410,12 +421,18 @@ class _AddAllergiesState extends State { AppButton( title: TranslationBase.of(context).add.toUpperCase(), onPressed: () { - MySelectedAllergy mySelectedAllergy = new MySelectedAllergy( - remark: remarkController.text, - selectedAllergy: _selectedAllergy, - isChecked: true, - selectedAllergySeverity: _selectedAllergySeverity,); - widget.addAllergiesFun(mySelectedAllergy); + setState(() { + isFormSubmitted = true; + }); + if(_selectedAllergy !=null && _selectedAllergySeverity !=null) { + MySelectedAllergy mySelectedAllergy = new MySelectedAllergy( + remark: remarkController.text, + selectedAllergy: _selectedAllergy, + isChecked: true, + selectedAllergySeverity: _selectedAllergySeverity,); + widget.addAllergiesFun(mySelectedAllergy); + } + }, ), ] @@ -433,3 +450,4 @@ class _AddAllergiesState extends State { + diff --git a/lib/widgets/patients/profile/soap_update/subjective/update_history_widget.dart b/lib/widgets/patients/profile/soap_update/subjective/update_history_widget.dart index 9a7cba01..28f9f466 100644 --- a/lib/widgets/patients/profile/soap_update/subjective/update_history_widget.dart +++ b/lib/widgets/patients/profile/soap_update/subjective/update_history_widget.dart @@ -10,6 +10,7 @@ import 'package:doctor_app_flutter/widgets/shared/Text.dart'; import 'package:doctor_app_flutter/widgets/shared/TextFields.dart'; import 'package:doctor_app_flutter/widgets/shared/app_scaffold_widget.dart'; import 'package:doctor_app_flutter/widgets/shared/master_key_checkbox_search_widget.dart'; +import 'package:doctor_app_flutter/widgets/shared/network_base_view.dart'; import 'package:eva_icons_flutter/eva_icons_flutter.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; @@ -271,6 +272,9 @@ class _AddHistoryDialogState extends State { onModelReady: (model) async { if (model.historyFamilyList.length == 0) { await model.getMasterLookup(MasterKeysService.HistoryFamily); + setState(() { + + }); } }, builder: (_, model, w) => AppScaffold( @@ -313,62 +317,71 @@ class _AddHistoryDialogState extends State { }, scrollDirection: Axis.horizontal, children: [ - MasterKeyCheckboxSearchWidget( - model: model, - masterList: model.historyFamilyList, - removeHistory: (history){ - setState(() { - widget.removeHistory(history); - }); - }, - addHistory: (history){ - setState(() { - createAndAddHistory( - history); - }); - }, - addSelectedHistories: (){ - widget.addSelectedHistories(); - }, - isServiceSelected: (master) =>isServiceSelected(master), + NetworkBaseView( + baseViewModel: model, + child: MasterKeyCheckboxSearchWidget( + model: model, + masterList: model.historyFamilyList, + removeHistory: (history){ + setState(() { + widget.removeHistory(history); + }); + }, + addHistory: (history){ + setState(() { + createAndAddHistory( + history); + }); + }, + addSelectedHistories: (){ + widget.addSelectedHistories(); + }, + isServiceSelected: (master) =>isServiceSelected(master), + ), ), - MasterKeyCheckboxSearchWidget( - model: model, - masterList: model.mergeHistorySurgicalWithHistorySportList, - removeHistory: (history){ - setState(() { - widget.removeHistory(history); - }); - }, - addHistory: (history){ - setState(() { - createAndAddHistory( - history); - }); - }, - addSelectedHistories: (){ - widget.addSelectedHistories(); - }, - isServiceSelected: (master) =>isServiceSelected(master), + NetworkBaseView( + baseViewModel: model, + child: MasterKeyCheckboxSearchWidget( + model: model, + masterList: model.mergeHistorySurgicalWithHistorySportList, + removeHistory: (history){ + setState(() { + widget.removeHistory(history); + }); + }, + addHistory: (history){ + setState(() { + createAndAddHistory( + history); + }); + }, + addSelectedHistories: (){ + widget.addSelectedHistories(); + }, + isServiceSelected: (master) =>isServiceSelected(master), + ), ), - MasterKeyCheckboxSearchWidget( - model: model, - masterList: model.historyMedicalList, - removeHistory: (history){ - setState(() { - widget.removeHistory(history); - }); - }, - addHistory: (history){ - setState(() { - createAndAddHistory( - history); - }); - }, - addSelectedHistories: (){ - widget.addSelectedHistories(); - }, - isServiceSelected: (master) =>isServiceSelected(master), + NetworkBaseView( + baseViewModel: model, + child: MasterKeyCheckboxSearchWidget( + model: model, + masterList: model.historyMedicalList, + removeHistory: (history){ + setState(() { + widget.removeHistory(history); + }); + }, + addHistory: (history){ + setState(() { + createAndAddHistory( + history); + }); + }, + addSelectedHistories: (){ + widget.addSelectedHistories(); + }, + isServiceSelected: (master) =>isServiceSelected(master), + ), ), ], ), diff --git a/lib/widgets/patients/profile/soap_update/update_assessment_page.dart b/lib/widgets/patients/profile/soap_update/update_assessment_page.dart index 10bfc120..93d56af2 100644 --- a/lib/widgets/patients/profile/soap_update/update_assessment_page.dart +++ b/lib/widgets/patients/profile/soap_update/update_assessment_page.dart @@ -23,6 +23,8 @@ import 'package:eva_icons_flutter/eva_icons_flutter.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'custom_validation_error.dart'; + class UpdateAssessmentPage extends StatefulWidget { final Function changePageViewIndex; List mySelectedAssessmentList; @@ -41,7 +43,6 @@ class _UpdateAssessmentPageState extends State { bool isAssessmentExpand = false; @override Widget build(BuildContext context) { - final screenSize = MediaQuery.of(context).size; return BaseView( onModelReady: (model) async{ @@ -152,12 +153,10 @@ class _UpdateAssessmentPageState extends State { model: model); }, readOnly: true, - // hintColor: Colors.black, suffixIcon: EvaIcons.plusCircleOutline, suffixIconColor: AppGlobal .appPrimaryColor, fontWeight: FontWeight.w600, - // controller: messageController, validator: (value) { if (value == null) return TranslationBase @@ -217,7 +216,7 @@ class _UpdateAssessmentPageState extends State { MainAxisAlignment.start, children: [ AppText( - "Appointment #: ", + TranslationBase.of(context).appointmentNo, fontWeight: FontWeight .bold, fontSize: 16, @@ -250,7 +249,7 @@ class _UpdateAssessmentPageState extends State { MainAxisAlignment.start, children: [ AppText( - "Type : ", + TranslationBase.of(context).type +':', fontWeight: FontWeight .bold, fontSize: 16, @@ -270,7 +269,7 @@ class _UpdateAssessmentPageState extends State { MainAxisAlignment.start, children: [ AppText( - "Doc : ", + TranslationBase.of(context).doc, fontWeight: FontWeight .bold, fontSize: 16, @@ -402,6 +401,7 @@ class _UpdateAssessmentPageState extends State { addSelectedAssessment: (MySelectedAssessment mySelectedAssessment, bool isUpdate) async { setState(() { + widget.mySelectedAssessmentList.add(mySelectedAssessment); }); }); @@ -416,7 +416,6 @@ class AddAssessmentDetails extends StatefulWidget { final Function(MySelectedAssessment mySelectedAssessment, bool isUpdate) addSelectedAssessment; final PatiantInformtion patientInfo; final bool isUpdate; - AddAssessmentDetails( {Key key, this.mySelectedAssessment, this.addSelectedAssessment, this.patientInfo, this.isUpdate = false, this.mySelectedAssessmentList}); @@ -429,6 +428,7 @@ class _AddAssessmentDetailsState extends State { TextEditingController remarkController = TextEditingController(); TextEditingController appointmentIdController = TextEditingController(); GlobalKey key = new GlobalKey>(); + bool isFormSubmitted = false; @override Widget build(BuildContext context) { @@ -552,6 +552,9 @@ class _AddAssessmentDetailsState extends State { ), ), ), + if(isFormSubmitted && widget.mySelectedAssessment + .selectedICD == null) + CustomValidationError(), SizedBox( height: 10, ), @@ -598,6 +601,9 @@ class _AddAssessmentDetailsState extends State { ), ), ), + if(isFormSubmitted && widget.mySelectedAssessment + .selectedDiagnosisCondition == null) + CustomValidationError(), SizedBox( height: 10, ), @@ -644,6 +650,9 @@ class _AddAssessmentDetailsState extends State { ), ), ), + if(isFormSubmitted && widget.mySelectedAssessment + .selectedDiagnosisType == null) + CustomValidationError(), SizedBox( height: 10, ), @@ -671,9 +680,12 @@ class _AddAssessmentDetailsState extends State { height: 10, ), AppButton( - title: "Add".toUpperCase(), + title: (widget.isUpdate?TranslationBase.of(context).update:TranslationBase.of(context).add).toUpperCase(), loading: model.state == ViewState.BusyLocal, onPressed: () async { + setState(() { + isFormSubmitted = true; + }); widget.mySelectedAssessment.remark = remarkController.text; widget.mySelectedAssessment @@ -695,10 +707,6 @@ class _AddAssessmentDetailsState extends State { model: model, mySelectedAssessment: widget .mySelectedAssessment); - } else { - helpers.showErrorToast(TranslationBase - .of(context) - .requiredMsg); } }, ), @@ -755,7 +763,8 @@ class _AddAssessmentDetailsState extends State { mySelectedAssessment.icdCode10ID = mySelectedAssessment.selectedICD.code; if (!isUpdate) { - widget.mySelectedAssessmentList.add(mySelectedAssessment); + // widget.mySelectedAssessmentList.add(mySelectedAssessment); + widget.addSelectedAssessment(mySelectedAssessment,isUpdate); } Navigator.of(context).pop(); } diff --git a/lib/widgets/patients/profile/soap_update/update_objective_page.dart b/lib/widgets/patients/profile/soap_update/update_objective_page.dart index 0c8bece6..9bd38666 100644 --- a/lib/widgets/patients/profile/soap_update/update_objective_page.dart +++ b/lib/widgets/patients/profile/soap_update/update_objective_page.dart @@ -315,7 +315,7 @@ class _UpdateObjectivePageState extends State { fontWeight: FontWeight.w600, maxLines: 25, minLines: 4, - controller: remarksController, + // controller: remarksController, validator: (value) { if (value == null) return TranslationBase.of(context) @@ -397,10 +397,10 @@ class _UpdateObjectivePageState extends State { widget.changePageViewIndex(2); } } else { - helpers.showErrorToast(TranslationBase.of(context).requiredMsg); - } + widget.changePageViewIndex(2); - widget.changePageViewIndex(2); + // helpers.showErrorToast(TranslationBase.of(context).requiredMsg); + } } removeExamination(MasterKeyModel masterKey) { diff --git a/lib/widgets/patients/profile/soap_update/update_plan_page.dart b/lib/widgets/patients/profile/soap_update/update_plan_page.dart index a91447d6..a3c2cdd2 100644 --- a/lib/widgets/patients/profile/soap_update/update_plan_page.dart +++ b/lib/widgets/patients/profile/soap_update/update_plan_page.dart @@ -51,8 +51,6 @@ class _UpdatePlanPageState extends State { @override Widget build(BuildContext context) { - final screenSize = MediaQuery.of(context).size; - return BaseView( onModelReady: (model) async { GetGetProgressNoteReqModel getGetProgressNoteReqModel = @@ -115,7 +113,7 @@ class _UpdatePlanPageState extends State { ), Column( children: [ - if(model.patientProgressNoteList.isEmpty) + if(model.patientProgressNoteList.isEmpty || progressNoteController.text !='') Container( margin: EdgeInsets.only(left: 10, right: 10, top: 15), @@ -142,7 +140,7 @@ class _UpdatePlanPageState extends State { SizedBox( height: 20, ), - if (progressNoteController.text.isNotEmpty) + if (progressNoteController.text !='') Container( margin: EdgeInsets.only(left: 5, right: 5, top: 15), @@ -287,13 +285,13 @@ class _UpdatePlanPageState extends State { appointmentNo: widget.patientInfo.appointmentNo, planNote: progressNoteController.text, doctorID: '', editedBy: ''); - // if(model.patientProgressNoteList.isEmpty){ + if(model.patientProgressNoteList.isEmpty){ await model.postProgressNote(postProgressNoteRequestModel); - // }else { - // await model.patchProgressNote(postProgressNoteRequestModel); - // - // } + }else { + await model.patchProgressNote(postProgressNoteRequestModel); + + } if (model.state == ViewState.ErrorLocal) { helpers.showErrorToast(model.error); @@ -352,6 +350,9 @@ class _UpdatePlanPageState extends State { AppButton( title: "Add".toUpperCase(), onPressed: () { + setState(() { + print(progressNoteController.text); + }); Navigator.of(context).pop(); }, ), diff --git a/lib/widgets/shared/app_loader_widget.dart b/lib/widgets/shared/app_loader_widget.dart index 65a5f231..7b1f1718 100644 --- a/lib/widgets/shared/app_loader_widget.dart +++ b/lib/widgets/shared/app_loader_widget.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:progress_hud_v2/progress_hud.dart'; +import 'loader/gif_loader_container.dart'; + /* *@author: Elham Rababah *@Date:19/4/2020 @@ -41,6 +43,18 @@ class _AppLoaderWidgetState extends State { @override Widget build(BuildContext context) { - return Positioned(child: _progressHUD); + return Container( + height: MediaQuery.of(context).size.height, + + child: Stack( + children: [ + Container( + color: Colors.grey.withOpacity(0.6), + ), + Container(child: GifLoaderContainer(), margin: EdgeInsets.only( + bottom: MediaQuery.of(context).size.height * 0.09)) + ], + ), + ); } } diff --git a/lib/widgets/shared/app_text_form_field.dart b/lib/widgets/shared/app_text_form_field.dart index 4c2573cd..82a273bb 100644 --- a/lib/widgets/shared/app_text_form_field.dart +++ b/lib/widgets/shared/app_text_form_field.dart @@ -4,10 +4,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:hexcolor/hexcolor.dart'; -// OWNER : Ibrahim albitar -// DATE : 19-04-2020 -// DESCRIPTION : Custom Text Form Field for app. - class AppTextFormField extends FormField { AppTextFormField( {FormFieldSetter onSaved, @@ -41,6 +37,7 @@ class AppTextFormField extends FormField { obscureText: obscureText, focusNode: focusNode, keyboardType: textInputType, + readOnly: readOnly, inputFormatters: [ FilteringTextInputFormatter.allow( RegExp(inputFormatter)), diff --git a/lib/widgets/shared/loader/gif_loader_container.dart b/lib/widgets/shared/loader/gif_loader_container.dart new file mode 100644 index 00000000..b7a20339 --- /dev/null +++ b/lib/widgets/shared/loader/gif_loader_container.dart @@ -0,0 +1,43 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_gifimage/flutter_gifimage.dart'; + +class GifLoaderContainer extends StatefulWidget { + @override + _GifLoaderContainerState createState() => _GifLoaderContainerState(); +} + +class _GifLoaderContainerState extends State + with TickerProviderStateMixin { + GifController controller1; + + @override + void initState() { + controller1 = GifController(vsync: this); + + WidgetsBinding.instance.addPostFrameCallback((_) { + controller1.repeat( + min: 0, max: 11, period: Duration(milliseconds: 750), reverse: true); + }); + super.initState(); + } + + @override + void dispose() { + controller1.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Center( + //progress-loading.gif + child: Container( + // margin: EdgeInsets.only(bottom: 40), + child: GifImage( + controller: controller1, + image: AssetImage( + "assets/images/progress-loading-red.gif"), //NetworkImage("http://img.mp.itc.cn/upload/20161107/5cad975eee9e4b45ae9d3c1238ccf91e.jpg"), + ), + )); + } +} \ No newline at end of file diff --git a/lib/widgets/shared/loader/gif_loader_dialog_utils.dart b/lib/widgets/shared/loader/gif_loader_dialog_utils.dart new file mode 100644 index 00000000..9b45bba1 --- /dev/null +++ b/lib/widgets/shared/loader/gif_loader_dialog_utils.dart @@ -0,0 +1,14 @@ +import 'package:flutter/material.dart'; + +import 'gif_loader_container.dart'; + + +class GifLoaderDialogUtils { + static showMyDialog(BuildContext context) { + showDialog(context: context, child: GifLoaderContainer()); + } + + static hideDialog(BuildContext context) { + Navigator.of(context).pop(); + } +} diff --git a/lib/widgets/shared/master_key_checkbox_search_widget.dart b/lib/widgets/shared/master_key_checkbox_search_widget.dart index aafb8adc..dd9e2f3d 100644 --- a/lib/widgets/shared/master_key_checkbox_search_widget.dart +++ b/lib/widgets/shared/master_key_checkbox_search_widget.dart @@ -53,71 +53,68 @@ class _MasterKeyCheckboxSearchWidgetState extends State animation, + Animation secondaryAnimation, + ) => + page, + transitionDuration: Duration(milliseconds: 300), + transitionsBuilder: ( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + Widget child, + ) { + return FadeTransition( + opacity: animation, + child: child + ); + } + ); +} \ No newline at end of file diff --git a/lib/widgets/transitions/slide_up_page.dart b/lib/widgets/transitions/slide_up_page.dart new file mode 100644 index 00000000..2c138b9e --- /dev/null +++ b/lib/widgets/transitions/slide_up_page.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; + +///Slide Up Page Route +/// [widget] widget we need to slide up +/// [fullscreenDialog] show the widget as full screen dialog +/// [opaque] When an opaque route's entrance transition is complete, the routes behind the opaque route will not be built to save resources. +class SlideUpPageRoute extends PageRouteBuilder { + final Widget widget; + final bool fullscreenDialog; + final bool opaque; + + SlideUpPageRoute( + {this.widget, this.fullscreenDialog = false, this.opaque = true}) + : super( + pageBuilder: ( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + ) { + return widget; + }, + fullscreenDialog: fullscreenDialog, + opaque: opaque, + barrierColor: Color.fromRGBO(0, 0, 0, 0.5), + barrierDismissible: true, + transitionDuration: Duration(milliseconds: 800), + transitionsBuilder: ((BuildContext context, + Animation animation, + Animation secondaryAnimation, + Widget child) { + var begin = Offset(0.0, 1.0); + var end = Offset.zero; + var curve = Curves.easeInOutQuint; + + var tween = + Tween(begin: begin, end: end).chain(CurveTween(curve: curve)); + + return SlideTransition( + position: animation.drive(tween), child: child); + }), + ); +} diff --git a/pubspec.lock b/pubspec.lock index 5650f5f9..77edb88a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -70,7 +70,7 @@ packages: name: build url: "https://pub.dartlang.org" source: hosted - version: "1.6.0" + version: "1.6.1" build_config: dependency: transitive description: @@ -84,35 +84,35 @@ packages: name: build_daemon url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "2.1.6" build_modules: dependency: transitive description: name: build_modules url: "https://pub.dartlang.org" source: hosted - version: "3.0.2" + version: "3.0.3" build_resolvers: dependency: transitive description: name: build_resolvers url: "https://pub.dartlang.org" source: hosted - version: "1.5.1" + version: "1.5.2" build_runner: dependency: "direct dev" description: name: build_runner url: "https://pub.dartlang.org" source: hosted - version: "1.10.11" + version: "1.10.13" build_runner_core: dependency: transitive description: name: build_runner_core url: "https://pub.dartlang.org" source: hosted - version: "6.1.5" + version: "6.1.6" build_web_compilers: dependency: "direct dev" description: @@ -189,7 +189,7 @@ packages: name: code_builder url: "https://pub.dartlang.org" source: hosted - version: "3.5.0" + version: "3.6.0" collection: dependency: transitive description: @@ -281,6 +281,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.1" + equatable: + dependency: transitive + description: + name: equatable + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.5" eva_icons_flutter: dependency: "direct main" description: @@ -316,6 +323,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "5.2.1" + firebase_core: + dependency: transitive + description: + name: firebase_core + url: "https://pub.dartlang.org" + source: hosted + version: "0.5.3" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.1+1" + firebase_messaging: + dependency: "direct main" + description: + name: firebase_messaging + url: "https://pub.dartlang.org" + source: hosted + version: "7.0.3" fixnum: dependency: transitive description: @@ -323,6 +358,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.10.11" + fl_chart: + dependency: "direct main" + description: + name: fl_chart + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.2" flutter: dependency: "direct main" description: flutter @@ -342,6 +384,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.4" + flutter_gifimage: + dependency: "direct main" + description: + name: flutter_gifimage + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" flutter_localizations: dependency: "direct main" description: flutter @@ -461,7 +510,7 @@ packages: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.3-nullsafety.1" + version: "0.6.2" json_annotation: dependency: transitive description: @@ -546,6 +595,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0-nullsafety.1" + path_drawing: + dependency: transitive + description: + name: path_drawing + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.1+1" + path_parsing: + dependency: transitive + description: + name: path_parsing + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" path_provider_linux: dependency: transitive description: @@ -643,7 +706,7 @@ packages: name: provider url: "https://pub.dartlang.org" source: hosted - version: "4.3.2+3" + version: "4.3.2+4" pub_semver: dependency: transitive description: @@ -671,7 +734,7 @@ packages: name: scratch_space url: "https://pub.dartlang.org" source: hosted - version: "0.0.4+2" + version: "0.0.4+3" shared_preferences: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 57ed4cbb..887ac913 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -59,6 +59,13 @@ dependencies: #Dependency Injection get_it: ^4.0.2 + #chart + fl_chart: ^0.12.1 + + #firebase + firebase_messaging: ^7.0.0 + #GIF image + flutter_gifimage: ^1.0.1 #Autocomplete TextField autocomplete_textfield: ^1.7.3 @@ -93,7 +100,7 @@ flutter: assets: - assets/images/ - assets/images/dashboard/ - + - assets/images/login/ # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware.