diff --git a/android/app/build.gradle b/android/app/build.gradle index 8a164e5..d4f4f6e 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -44,8 +44,8 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.queuing_system" - minSdkVersion flutter.minSdkVersion - targetSdkVersion flutter.targetSdkVersion + minSdkVersion localProperties.getProperty('flutter.minSdkVersion').toInteger() + targetSdkVersion localProperties.getProperty('flutter.targetSdkVersion').toInteger() versionCode flutterVersionCode.toInteger() versionName flutterVersionName } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 8117512..9b4b6a4 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,10 @@ + + + + + @@ -30,5 +36,5 @@ - + diff --git a/android/build.gradle b/android/build.gradle index 24047dc..9e8dea7 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = '1.6.0' repositories { google() mavenCentral() diff --git a/assets/fonts/Poppins/Poppins-Bold.ttf b/assets/fonts/Poppins/Poppins-Bold.ttf new file mode 100644 index 0000000..b94d47f Binary files /dev/null and b/assets/fonts/Poppins/Poppins-Bold.ttf differ diff --git a/assets/fonts/Poppins/Poppins-Medium.ttf b/assets/fonts/Poppins/Poppins-Medium.ttf new file mode 100644 index 0000000..e90e87e Binary files /dev/null and b/assets/fonts/Poppins/Poppins-Medium.ttf differ diff --git a/assets/fonts/Poppins/Poppins-Regular.ttf b/assets/fonts/Poppins/Poppins-Regular.ttf new file mode 100644 index 0000000..be06e7f Binary files /dev/null and b/assets/fonts/Poppins/Poppins-Regular.ttf differ diff --git a/assets/fonts/Poppins/Poppins-SemiBold.ttf b/assets/fonts/Poppins/Poppins-SemiBold.ttf new file mode 100644 index 0000000..8987d80 Binary files /dev/null and b/assets/fonts/Poppins/Poppins-SemiBold.ttf differ diff --git a/assets/images/cloud_logo.png b/assets/images/cloud_logo.png new file mode 100644 index 0000000..6505325 Binary files /dev/null and b/assets/images/cloud_logo.png differ diff --git a/assets/images/doctoricon.svg b/assets/images/doctoricon.svg new file mode 100644 index 0000000..a83af92 --- /dev/null +++ b/assets/images/doctoricon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/hmglogo.svg b/assets/images/hmglogo.svg new file mode 100644 index 0000000..d2b7d58 --- /dev/null +++ b/assets/images/hmglogo.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/assets/images/nurseicon.svg b/assets/images/nurseicon.svg new file mode 100644 index 0000000..55de01f --- /dev/null +++ b/assets/images/nurseicon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/undraw_connected_world_wuay.png b/assets/images/undraw_connected_world_wuay.png new file mode 100644 index 0000000..6e8eb47 Binary files /dev/null and b/assets/images/undraw_connected_world_wuay.png differ diff --git a/assets/images/wait.svg b/assets/images/wait.svg new file mode 100644 index 0000000..854fb2b --- /dev/null +++ b/assets/images/wait.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/assets/voice_ar/0.mp3 b/assets/voice_ar/0.mp3 new file mode 100644 index 0000000..2c1cf4f Binary files /dev/null and b/assets/voice_ar/0.mp3 differ diff --git a/assets/voice_ar/1.mp3 b/assets/voice_ar/1.mp3 new file mode 100644 index 0000000..b05d617 Binary files /dev/null and b/assets/voice_ar/1.mp3 differ diff --git a/assets/voice_ar/2.mp3 b/assets/voice_ar/2.mp3 new file mode 100644 index 0000000..5bfe89e Binary files /dev/null and b/assets/voice_ar/2.mp3 differ diff --git a/assets/voice_ar/3.mp3 b/assets/voice_ar/3.mp3 new file mode 100644 index 0000000..68c1af5 Binary files /dev/null and b/assets/voice_ar/3.mp3 differ diff --git a/assets/voice_ar/4.mp3 b/assets/voice_ar/4.mp3 new file mode 100644 index 0000000..3a3e2ec Binary files /dev/null and b/assets/voice_ar/4.mp3 differ diff --git a/assets/voice_ar/5.mp3 b/assets/voice_ar/5.mp3 new file mode 100644 index 0000000..e2e0fee Binary files /dev/null and b/assets/voice_ar/5.mp3 differ diff --git a/assets/voice_ar/6.mp3 b/assets/voice_ar/6.mp3 new file mode 100644 index 0000000..6e5646d Binary files /dev/null and b/assets/voice_ar/6.mp3 differ diff --git a/assets/voice_ar/7.mp3 b/assets/voice_ar/7.mp3 new file mode 100644 index 0000000..ba90910 Binary files /dev/null and b/assets/voice_ar/7.mp3 differ diff --git a/assets/voice_ar/8.mp3 b/assets/voice_ar/8.mp3 new file mode 100644 index 0000000..5b2e025 Binary files /dev/null and b/assets/voice_ar/8.mp3 differ diff --git a/assets/voice_ar/9.mp3 b/assets/voice_ar/9.mp3 new file mode 100644 index 0000000..4112f24 Binary files /dev/null and b/assets/voice_ar/9.mp3 differ diff --git a/assets/voice_ar/ticket_number.mp3 b/assets/voice_ar/ticket_number.mp3 new file mode 100644 index 0000000..3a1ce47 Binary files /dev/null and b/assets/voice_ar/ticket_number.mp3 differ diff --git a/assets/voice_ar/visit_doctor.mp3 b/assets/voice_ar/visit_doctor.mp3 new file mode 100644 index 0000000..6bf38d9 Binary files /dev/null and b/assets/voice_ar/visit_doctor.mp3 differ diff --git a/assets/voice_ar/visit_nurse.mp3 b/assets/voice_ar/visit_nurse.mp3 new file mode 100644 index 0000000..cfa32e5 Binary files /dev/null and b/assets/voice_ar/visit_nurse.mp3 differ diff --git a/assets/voice_en/0.mp3 b/assets/voice_en/0.mp3 new file mode 100644 index 0000000..5603d80 Binary files /dev/null and b/assets/voice_en/0.mp3 differ diff --git a/assets/voice_en/1.mp3 b/assets/voice_en/1.mp3 new file mode 100644 index 0000000..f5cced9 Binary files /dev/null and b/assets/voice_en/1.mp3 differ diff --git a/assets/voice_en/2.mp3 b/assets/voice_en/2.mp3 new file mode 100644 index 0000000..f0c6084 Binary files /dev/null and b/assets/voice_en/2.mp3 differ diff --git a/assets/voice_en/3.mp3 b/assets/voice_en/3.mp3 new file mode 100644 index 0000000..da489e8 Binary files /dev/null and b/assets/voice_en/3.mp3 differ diff --git a/assets/voice_en/4.mp3 b/assets/voice_en/4.mp3 new file mode 100644 index 0000000..f76338c Binary files /dev/null and b/assets/voice_en/4.mp3 differ diff --git a/assets/voice_en/5.mp3 b/assets/voice_en/5.mp3 new file mode 100644 index 0000000..0cbc7de Binary files /dev/null and b/assets/voice_en/5.mp3 differ diff --git a/assets/voice_en/6.mp3 b/assets/voice_en/6.mp3 new file mode 100644 index 0000000..779ed79 Binary files /dev/null and b/assets/voice_en/6.mp3 differ diff --git a/assets/voice_en/7.mp3 b/assets/voice_en/7.mp3 new file mode 100644 index 0000000..28f2ea7 Binary files /dev/null and b/assets/voice_en/7.mp3 differ diff --git a/assets/voice_en/8.mp3 b/assets/voice_en/8.mp3 new file mode 100644 index 0000000..b1947c2 Binary files /dev/null and b/assets/voice_en/8.mp3 differ diff --git a/assets/voice_en/9.mp3 b/assets/voice_en/9.mp3 new file mode 100644 index 0000000..4e5453c Binary files /dev/null and b/assets/voice_en/9.mp3 differ diff --git a/assets/voice_en/A.mp3 b/assets/voice_en/A.mp3 new file mode 100644 index 0000000..9e7c9ba Binary files /dev/null and b/assets/voice_en/A.mp3 differ diff --git a/assets/voice_en/B.mp3 b/assets/voice_en/B.mp3 new file mode 100644 index 0000000..d4aedb3 Binary files /dev/null and b/assets/voice_en/B.mp3 differ diff --git a/assets/voice_en/C.mp3 b/assets/voice_en/C.mp3 new file mode 100644 index 0000000..e339eea Binary files /dev/null and b/assets/voice_en/C.mp3 differ diff --git a/assets/voice_en/D.mp3 b/assets/voice_en/D.mp3 new file mode 100644 index 0000000..29703e1 Binary files /dev/null and b/assets/voice_en/D.mp3 differ diff --git a/assets/voice_en/E.mp3 b/assets/voice_en/E.mp3 new file mode 100644 index 0000000..8233369 Binary files /dev/null and b/assets/voice_en/E.mp3 differ diff --git a/assets/voice_en/F.mp3 b/assets/voice_en/F.mp3 new file mode 100644 index 0000000..9e91029 Binary files /dev/null and b/assets/voice_en/F.mp3 differ diff --git a/assets/voice_en/G.mp3 b/assets/voice_en/G.mp3 new file mode 100644 index 0000000..6d466d9 Binary files /dev/null and b/assets/voice_en/G.mp3 differ diff --git a/assets/voice_en/H.mp3 b/assets/voice_en/H.mp3 new file mode 100644 index 0000000..d8db402 Binary files /dev/null and b/assets/voice_en/H.mp3 differ diff --git a/assets/voice_en/I.mp3 b/assets/voice_en/I.mp3 new file mode 100644 index 0000000..ec99690 Binary files /dev/null and b/assets/voice_en/I.mp3 differ diff --git a/assets/voice_en/J.mp3 b/assets/voice_en/J.mp3 new file mode 100644 index 0000000..20c4c7d Binary files /dev/null and b/assets/voice_en/J.mp3 differ diff --git a/assets/voice_en/K.mp3 b/assets/voice_en/K.mp3 new file mode 100644 index 0000000..435bb2a Binary files /dev/null and b/assets/voice_en/K.mp3 differ diff --git a/assets/voice_en/L.mp3 b/assets/voice_en/L.mp3 new file mode 100644 index 0000000..8782f98 Binary files /dev/null and b/assets/voice_en/L.mp3 differ diff --git a/assets/voice_en/M.mp3 b/assets/voice_en/M.mp3 new file mode 100644 index 0000000..241ab72 Binary files /dev/null and b/assets/voice_en/M.mp3 differ diff --git a/assets/voice_en/N.mp3 b/assets/voice_en/N.mp3 new file mode 100644 index 0000000..07845a5 Binary files /dev/null and b/assets/voice_en/N.mp3 differ diff --git a/assets/voice_en/O.mp3 b/assets/voice_en/O.mp3 new file mode 100644 index 0000000..4489e28 Binary files /dev/null and b/assets/voice_en/O.mp3 differ diff --git a/assets/voice_en/P.mp3 b/assets/voice_en/P.mp3 new file mode 100644 index 0000000..8b05b1b Binary files /dev/null and b/assets/voice_en/P.mp3 differ diff --git a/assets/voice_en/Q.mp3 b/assets/voice_en/Q.mp3 new file mode 100644 index 0000000..b19af46 Binary files /dev/null and b/assets/voice_en/Q.mp3 differ diff --git a/assets/voice_en/R.mp3 b/assets/voice_en/R.mp3 new file mode 100644 index 0000000..06a7061 Binary files /dev/null and b/assets/voice_en/R.mp3 differ diff --git a/assets/voice_en/S.mp3 b/assets/voice_en/S.mp3 new file mode 100644 index 0000000..61cd779 Binary files /dev/null and b/assets/voice_en/S.mp3 differ diff --git a/assets/voice_en/T.mp3 b/assets/voice_en/T.mp3 new file mode 100644 index 0000000..87940cf Binary files /dev/null and b/assets/voice_en/T.mp3 differ diff --git a/assets/voice_en/U.mp3 b/assets/voice_en/U.mp3 new file mode 100644 index 0000000..6046904 Binary files /dev/null and b/assets/voice_en/U.mp3 differ diff --git a/assets/voice_en/V.mp3 b/assets/voice_en/V.mp3 new file mode 100644 index 0000000..38b6966 Binary files /dev/null and b/assets/voice_en/V.mp3 differ diff --git a/assets/voice_en/W.mp3 b/assets/voice_en/W.mp3 new file mode 100644 index 0000000..a0b575a Binary files /dev/null and b/assets/voice_en/W.mp3 differ diff --git a/assets/voice_en/X.mp3 b/assets/voice_en/X.mp3 new file mode 100644 index 0000000..3f4ae66 Binary files /dev/null and b/assets/voice_en/X.mp3 differ diff --git a/assets/voice_en/Y.mp3 b/assets/voice_en/Y.mp3 new file mode 100644 index 0000000..bfac3c8 Binary files /dev/null and b/assets/voice_en/Y.mp3 differ diff --git a/assets/voice_en/Z.mp3 b/assets/voice_en/Z.mp3 new file mode 100644 index 0000000..dcc0cc5 Binary files /dev/null and b/assets/voice_en/Z.mp3 differ diff --git a/assets/voice_en/ticket_number.mp3 b/assets/voice_en/ticket_number.mp3 new file mode 100644 index 0000000..ca4b295 Binary files /dev/null and b/assets/voice_en/ticket_number.mp3 differ diff --git a/assets/voice_en/visit_doctor.mp3 b/assets/voice_en/visit_doctor.mp3 new file mode 100644 index 0000000..fa3f018 Binary files /dev/null and b/assets/voice_en/visit_doctor.mp3 differ diff --git a/assets/voice_en/visit_nurse.mp3 b/assets/voice_en/visit_nurse.mp3 new file mode 100644 index 0000000..f60684d Binary files /dev/null and b/assets/voice_en/visit_nurse.mp3 differ diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 8d4492f..9625e10 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 9.0 + 11.0 diff --git a/ios/Podfile b/ios/Podfile index 1e8c3c9..88359b2 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '9.0' +# platform :ios, '11.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 0cb89ab..305bc17 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,29 +1,47 @@ PODS: + - audio_session (0.0.1): + - Flutter - connectivity (0.0.1): - Flutter - Reachability - Flutter (1.0.0) + - just_audio (0.0.1): + - Flutter + - path_provider_ios (0.0.1): + - Flutter - Reachability (3.2) DEPENDENCIES: + - audio_session (from `.symlinks/plugins/audio_session/ios`) - connectivity (from `.symlinks/plugins/connectivity/ios`) - Flutter (from `Flutter`) + - just_audio (from `.symlinks/plugins/just_audio/ios`) + - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`) SPEC REPOS: trunk: - Reachability EXTERNAL SOURCES: + audio_session: + :path: ".symlinks/plugins/audio_session/ios" connectivity: :path: ".symlinks/plugins/connectivity/ios" Flutter: :path: Flutter + just_audio: + :path: ".symlinks/plugins/just_audio/ios" + path_provider_ios: + :path: ".symlinks/plugins/path_provider_ios/ios" SPEC CHECKSUMS: + audio_session: 4f3e461722055d21515cf3261b64c973c062f345 connectivity: c4130b2985d4ef6fd26f9702e886bd5260681467 - Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a + Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa + path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02 Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 -PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c +PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 -COCOAPODS: 1.11.2 +COCOAPODS: 1.11.3 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 7046dae..6364bea 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -340,7 +340,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -418,7 +418,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -467,7 +467,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 81eb537..256543f 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -43,5 +43,7 @@ UIViewControllerBasedStatusBarAppearance + CADisableMinimumFrameDurationOnPhone + diff --git a/lib/core/api.dart b/lib/core/api.dart new file mode 100644 index 0000000..e64c53d --- /dev/null +++ b/lib/core/api.dart @@ -0,0 +1,61 @@ +import 'dart:developer'; + +import 'package:flutter/cupertino.dart'; +import 'package:queuing_system/core/base/base_app_client.dart'; +import 'package:queuing_system/core/response_model/patient_call.dart'; + +const _getCallRequestInfoByClinicInfo = "/GetCallRequestInfoByClinincInfo"; +const _call_UpdateNotIsQueueRecordByIDAsync = "/Call_UpdateNotIsQueueRecordByID"; + +class API { + static getCallRequestInfoByClinicInfo(String deviceIp, {@required Function(List) onSuccess, @required Function(dynamic) onFailure}) async { + final body = {"IPAdress": deviceIp}; + BaseAppClient.post(_getCallRequestInfoByClinicInfo, + body: body, + onSuccess: (response, status) { + if (status == 200) { + var calledByNurse = (response["CalledByNurse"] as List).map((j) => Tickets.fromJson(j)).toList(); + log("calledByNurse Length: ${calledByNurse.length}"); + + final patients = (response["ClinicCurrentPatient"] as List).map((j) => Tickets.fromJson(j)).toList(); + log("patients Length: ${patients.length}"); + calledByNurse.addAll(patients); + + + // calledByNurse.sort((a, b) => a.callNo.compareTo(b.callNo)); + + onSuccess(calledByNurse.reversed.toList()); + } else { + onFailure(response); + } + }, + onFailure: (error, status) => onFailure(error)); + } + + static callUpdateNotIsQueueRecordByIDAsync(String deviceIp, {@required Tickets ticket, @required Function(List) onSuccess, @required Function(dynamic) onFailure}) async { + if (ticket.id == null) { + return; + } + + List _ticketsUpdated = []; + + // for (var ticket in tickets) { + final body = {"CallID": ticket.id}; + await BaseAppClient.post(_call_UpdateNotIsQueueRecordByIDAsync, + body: body, + onSuccess: (response, status) { + if (status == 200) { + ticket.callUpdated = true; + _ticketsUpdated.add(ticket); + } + }, + onFailure: (error, status) => onFailure(error)); + // } + + if (_ticketsUpdated.isNotEmpty) { + onSuccess(_ticketsUpdated); + } else { + onFailure(false); + } + } +} diff --git a/lib/core/base/app_scaffold_widget.dart b/lib/core/base/app_scaffold_widget.dart index 6d457ee..3443537 100644 --- a/lib/core/base/app_scaffold_widget.dart +++ b/lib/core/base/app_scaffold_widget.dart @@ -1,11 +1,8 @@ - import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:queuing_system/core/base/project_view_model.dart'; import 'package:queuing_system/widget/app_loader_widget.dart'; import 'package:queuing_system/widget/data_display/app_texts_widget.dart'; - - import 'base_view_model.dart'; import 'network_base_view.dart'; diff --git a/lib/core/base/base_app_client.dart b/lib/core/base/base_app_client.dart index a4eeabc..c6e5d6c 100644 --- a/lib/core/base/base_app_client.dart +++ b/lib/core/base/base_app_client.dart @@ -32,7 +32,7 @@ class BaseAppClient { if (statusCode < 200 || statusCode >= 400) { onFailure(Utils.generateContactAdminMsg(), statusCode); } else { - print(response.body.toString()); + print("Response: ${response.body.toString()}"); var parsed = json.decode(response.body.toString()); onSuccess(parsed, statusCode); } @@ -57,8 +57,8 @@ class BaseAppClient { try { // String token = await sharedPref.getString(TOKEN); - print("URL : $url"); - print("Body : ${json.encode(body)}"); + print("URL GET: $url"); + print("Body GET: ${json.encode(body)}"); var asd = json.encode(body); var asd2; if (await Utils.checkConnection()) { diff --git a/lib/core/config/config.dart b/lib/core/config/config.dart index 12ec7ca..3114524 100644 --- a/lib/core/config/config.dart +++ b/lib/core/config/config.dart @@ -5,446 +5,9 @@ const ONLY_NUMBERS = "[0-9]"; const ONLY_LETTERS = "[a-zA-Z &'\"]"; const ONLY_DATE = "[0-9/]"; const BASE_URL_LIVE_CARE = 'https://livecare.hmg.com/'; +const BASE_URL = 'https://uat.hmgwebservices.com/services/Nurses.svc/REST'; // UAT +// const BASE_URL = 'http://10.200.204.11:2222/Services/Nurses.svc/REST'; // const BASE_URL = 'https://hmgwebservices.com/'; -const BASE_URL = 'https://uat.hmgwebservices.com/'; -const PHARMACY_ITEMS_URL = "Services/Lists.svc/REST/GetPharmcyItems_Region_enh"; -const PHARMACY_LIST_URL = "Services/Patients.svc/REST/GetPharmcyList"; -const PATIENT_PROGRESS_NOTE_URL = - "Services/DoctorApplication.svc/REST/GetProgressNoteForInPatient"; -const PATIENT_INSURANCE_APPROVALS_URL = - "Services/DoctorApplication.svc/REST/GetApprovalStatusForInpatient"; -const PATIENT_REFER_TO_DOCTOR_URL = - "Services/DoctorApplication.svc/REST/ReferToDoctor"; -const PATIENT_GET_DOCTOR_BY_CLINIC_URL = - "Services/DoctorApplication.svc/REST/GetDoctorsByClinicID"; - -const PATIENT_GET_DOCTOR_BY_CLINIC_Hospital = - "Services/Doctors.svc/REST/SearchDoctorsByTime"; - -const GET_CLINICS_FOR_DOCTOR = - 'Services/DoctorApplication.svc/REST/GetClinicsForDoctor'; -const PATIENT_GET_LIST_REFERAL_URL = - "Services/Lists.svc/REST/GetList_STPReferralFrequency"; -const PATIENT_GET_CLINIC_BY_PROJECT_URL = - "Services/DoctorApplication.svc/REST/GetClinicsByProjectID"; -const PROJECT_GET_INFO = "Services/DoctorApplication.svc/REST/GetProjectInfo"; -const GET_CLINICS = "Services/DoctorApplication.svc/REST/GetClinics"; - -const GET_REFERRAL_FACILITIES = - 'Services/DoctorApplication.svc/REST/GetReferralFacilities'; - -const GET_PROJECTS = 'Services/DoctorApplication.svc/REST/GetProjectInfo'; - -const GET_PATIENT_VITAL_SIGN = - 'Services/Doctors.svc/REST/Doctor_GetPatientVitalSign'; -const GET_PATIENT_VITAL_SIGN_DATA = - 'Services/DoctorApplication.svc/REST/GetVitalSigns'; -const GET_PATIENT_LAB_OREDERS = - 'Services/DoctorApplication.svc/REST/GetPatientLabOreders'; -const GET_PRESCRIPTION = 'Services/Patients.svc/REST/GetPrescriptionApptList'; - -const GET_LIVECARE_PENDINGLIST = - 'Services/DoctorApplication.svc/REST/GetPendingPatientER'; -const START_LIVE_CARE_CALL = 'LiveCareApi/DoctorApp/CallPatient'; -const LIVE_CARE_STATISTICS_FOR_CERTAIN_DOCTOR_URL = - "Lists.svc/REST/DashBoard_GetLiveCareDoctorsStatsticsForCertainDoctor"; - -const GET_PRESCRIPTION_REPORT = - 'Services/Patients.svc/REST/GetPrescriptionReport'; - -const GT_MY_PATIENT_QUESTION = - 'Services/DoctorApplication.svc/REST/GtMyPatientsQuestions'; - -const PRM_SEARCH_PATIENT = - 'Services/Patients.svc/REST/GetPatientInformation_PRM'; - -const GET_PATIENT = 'Services/DoctorApplication.svc/REST/'; - -const GET_PRESCRIPTION_REPORT_FOR_IN_PATIENT = - 'Services/DoctorApplication.svc/REST/GetPrescriptionReportForInPatient'; - -const GET_MY_REFERRAL_PATIENT = - 'Services/DoctorApplication.svc/REST/GtMyReferralPatient'; - -const REFER_TO_DOCTOR = 'Services/DoctorApplication.svc/REST/ReferToDoctor'; - -const ADD_REFERRED_DOCTOR_REMARKS = - 'Services/DoctorApplication.svc/REST/AddReferredDoctorRemarks'; - -const GET_MY_REFERRED_PATIENT = - 'Services/DoctorApplication.svc/REST/GtMyReferredPatient'; - -const GET_MY_REFERRED_OUT_PATIENT = - 'Services/DoctorApplication.svc/REST/GtMyReferredOutPatient'; - -const GET_PENDING_REFERRAL_PATIENT = - 'Services/DoctorApplication.svc/REST/PendingReferrals'; - -const CREATE_REFERRAL_PATIENT = - 'Services/DoctorApplication.svc/REST/CreateReferral'; - -const RESPONSE_PENDING_REFERRAL_PATIENT = - 'Services/DoctorApplication.svc/REST/RespondReferral'; - -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'; - -const GET_PATIENT_LAB_RESULTS = - 'Services/DoctorApplication.svc/REST/GetPatientLabResults'; -const LOGIN_URL = 'Services/Sentry.svc/REST/MemberLogIN_New'; -const INSERT_DEVICE_IMEI = - '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/DoctorApplication.svc/REST/DoctorApp_GetDeviceDetailsByIMEI'; - -const SEND_ACTIVATION_CODE_BY_OTP_NOTIFICATION_TYPE = - 'Services/Sentry.svc/REST/DoctorApplication_SendActivationCodebyOTPNotificationType'; - -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'; - -const CHECK_ACTIVATION_CODE_FOR_DOCTOR_APP = - 'Services/DoctorApplication.svc/REST/CheckActivationCodeForDoctorApp'; - -const GET_DOC_PROFILES = 'Services/Doctors.svc/REST/GetDocProfiles'; -const TRANSFERT_TO_ADMIN = 'LiveCareApi/DoctorApp/TransferToAdmin'; -const SEND_SMS_INSTRUCTIONS = 'LiveCareApi/DoctorApp/SendSMSInstruction'; -const GET_ALTERNATIVE_SERVICE = 'LiveCareApi/DoctorApp/GetAlternativeServices'; -const END_CALL = 'LiveCareApi/DoctorApp/EndCall'; -const END_CALL_WITH_CHARGE = 'LiveCareApi/DoctorApp/CompleteCallWithCharge'; -const GET_DASHBOARD = - 'Services/DoctorApplication.svc/REST/GetDoctorDashboardKPI'; -const GET_SICKLEAVE_STATISTIC = - 'Services/DoctorApplication.svc/REST/PreSickLeaveStatistics'; -const ARRIVED_PATIENT_URL = - 'Services/DoctorApplication.svc/REST/PatientArrivalList'; -const ADD_SICK_LEAVE = 'Services/DoctorApplication.svc/REST/PostSickLeave'; -const GET_SICK_LEAVE = 'Services/Patients.svc/REST/GetPatientSickLeave'; -const EXTEND_SICK_LEAVE = 'Services/DoctorApplication.svc/REST/ExtendSickLeave'; - -const GET_MASTER_LOOKUP_LIST = 'Services/DoctorApplication.svc/REST/GetMasterLookUpList'; -const GET_COVERING_DOCTORS = - 'Services/DoctorApplication.svc/REST/GetCoveringDoctor'; -const ADD_RESCHDEULE = 'Services/DoctorApplication.svc/REST/PostRequisition'; -const UPDATE_RESCHDEULE = - 'Services/DoctorApplication.svc/REST/PatchRequisition'; -const GET_RESCHEDULE_LEAVE = - 'Services/DoctorApplication.svc/REST/GetRequisition'; -const GET_PRESCRIPTION_LIST = - 'Services/DoctorApplication.svc/REST/GetPrescription'; - -const POST_PRESCRIPTION_LIST = - 'Services/DoctorApplication.svc/REST/PostPrescription'; -const GET_PROCEDURE_LIST = - 'Services/DoctorApplication.svc/REST/GetOrderedProcedure'; -const POST_PROCEDURE_LIST = 'Services/DoctorApplication.svc/REST/PostProcedure'; - - -const GET_PATIENT_IN_PATIENT_LIST = - 'Services/DoctorApplication.svc/REST/GetMyInPatient'; - -const Verify_Referral_Doctor_Remarks = - 'Services/DoctorApplication.svc/REST/VerifyReferralDoctorRemarks'; - -///Lab Order -const GET_Patient_LAB_ORDERS = 'Services/Patients.svc/REST/GetPatientLabOrders'; -const GET_Patient_LAB_SPECIAL_RESULT = - 'Services/Patients.svc/REST/GetPatientLabSpecialResults'; -const SEND_LAB_RESULT_EMAIL = - 'Services/Notifications.svc/REST/SendLabReportEmail'; -const GET_Patient_LAB_RESULT = - 'Services/Patients.svc/REST/GetPatientLabResults'; -const GET_Patient_LAB_ORDERS_RESULT = - 'Services/Patients.svc/REST/GetPatientLabOrdersResults'; -const GET_PATIENT_LAB_ORDERS_RESULT_HISTORY_BY_DESCRIPTION = - 'Services/Patients.svc/REST/GetPatientLabOrdersResultsHistoryByDescription'; - -// SOAP - -const GET_ALLERGIES = 'Services/DoctorApplication.svc/REST/GetAllergies'; - -const POST_EPISODE = 'Services/DoctorApplication.svc/REST/PostEpisode'; -const POST_EPISODE_FOR_IN_PATIENT = - 'Services/DoctorApplication.svc/REST/PostEpisodeForInpatient'; - -const POST_ALLERGY = 'Services/DoctorApplication.svc/REST/PostAllergies'; -const POST_HISTORY = 'Services/DoctorApplication.svc/REST/PostHistory'; -const POST_CHIEF_COMPLAINT = - 'Services/DoctorApplication.svc/REST/PostChiefcomplaint'; -const POST_PHYSICAL_EXAM = - 'Services/DoctorApplication.svc/REST/PostPhysicalExam'; -const POST_PROGRESS_NOTE = - '/Services/DoctorApplication.svc/REST/PostProgressNote'; -const POST_ASSESSMENT = 'Services/DoctorApplication.svc/REST/PostAssessment'; - -const PATCH_ALLERGY = 'Services/DoctorApplication.svc/REST/PatchAllergies'; -const PATCH_HISTORY = 'Services/DoctorApplication.svc/REST/PatchHistory'; -const PATCH_CHIEF_COMPLAINT = - 'Services/DoctorApplication.svc/REST/PatchChiefcomplaint'; - -const PATCH_PHYSICAL_EXAM = - 'Services/DoctorApplication.svc/REST/PatchPhysicalExam'; -const PATCH_PROGRESS_NOTE = - 'Services/DoctorApplication.svc/REST/PatchProgressNote'; -const PATCH_ASSESSMENT = 'Services/DoctorApplication.svc/REST/PatchAssessment'; - -const GET_HISTORY = 'Services/DoctorApplication.svc/REST/GetHistory'; -const GET_CHIEF_COMPLAINT = - 'Services/DoctorApplication.svc/REST/GetChiefcomplaint'; -const GET_PHYSICAL_EXAM = 'Services/DoctorApplication.svc/REST/GetPhysicalExam'; -const GET_PROGRESS_NOTE = 'Services/DoctorApplication.svc/REST/GetProgressNote'; -const GET_ASSESSMENT = 'Services/DoctorApplication.svc/REST/GetAssessment'; - - -const GET_LIST_CATEGORISE = - 'Services/DoctorApplication.svc/REST/GetProcedureCategories'; - -const GET_CATEGORISE_PROCEDURE = - 'Services/DoctorApplication.svc/REST/GetProcedure'; -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'; -const GET_FLOORS = 'Services/DoctorApplication.svc/REST/GetFloors'; -const GET_WARDS = 'Services/DoctorApplication.svc/REST/GetWards'; -const GET_ROOM_CATEGORIES = - 'Services/DoctorApplication.svc/REST/GetRoomCategories'; -const GET_DIAGNOSIS_TYPES = - 'Services/DoctorApplication.svc/REST/DiagnosisTypes'; -const GET_DIET_TYPES = 'Services/DoctorApplication.svc/REST/DietTypes'; -const GET_ICD_CODES = 'Services/DoctorApplication.svc/REST/GetICDCodes'; -const POST_ADMISSION_REQUEST = - 'Services/DoctorApplication.svc/REST/PostAdmissionRequest'; -const GET_ITEM_BY_MEDICINE = - 'Services/DoctorApplication.svc/REST/GetItemByMedicineCode'; - -const GET_PROCEDURE_VALIDATION = - 'Services/DoctorApplication.svc/REST/ValidateProcedures'; -const GET_BOX_QUANTITY = - 'Services/DoctorApplication.svc/REST/CalculateBoxQuantity'; - -///GET ECG -const GET_ECG = "Services/Patients.svc/REST/HIS_GetPatientMuseResults"; - -const GET_MY_REFERRAL_INPATIENT = - "Services/DoctorApplication.svc/REST/GtMyReferralPatient"; - -const GET_MY_REFERRAL_OUT_PATIENT = - "Services/DoctorApplication.svc/REST/GtMyReferralForOutPatient"; - -const GET_MY_DISCHARGE_PATIENT = - "Services/DoctorApplication.svc/REST/GtMyDischargeReferralPatient"; -const GET_DISCHARGE_PATIENT = - "Services/DoctorApplication.svc/REST/GtMyDischargePatient"; - -const GET_PAtIENTS_INSURANCE_APPROVALS = - "Services/Patients.svc/REST/GetApprovalStatus"; - -const GET_RAD_IMAGE_URL = 'Services/Patients.svc/Rest/GetRadImageURL'; -const GET_PATIENT_ORDERS = 'Services/Patients.svc/REST/GetPatientRadOrders'; -const GET_IN_PATIENT_ORDERS = - 'Services/DoctorApplication.svc/REST/GetPatientRadResult'; - -///Prescriptions -const GET_PRESCRIPTIONS_ALL_ORDERS = - 'Services/Patients.svc/REST/PatientER_GetPatientAllPresOrders'; -const GET_PRESCRIPTION_REPORT_NEW = - 'Services/Patients.svc/REST/INP_GetPrescriptionReport'; -const SEND_PRESCRIPTION_EMAIL = - 'Services/Notifications.svc/REST/SendPrescriptionEmail'; -const GET_PRESCRIPTION_REPORT_ENH = - 'Services/Patients.svc/REST/GetPrescriptionReport_enh'; -const UPDATE_PROGRESS_NOTE_FOR_INPATIENT = - "Services/DoctorApplication.svc/REST/UpdateProgressNoteForInPatient"; -const CREATE_PROGRESS_NOTE_FOR_INPATIENT = - "Services/DoctorApplication.svc/REST/CreateProgressNoteForInPatient"; - -const GET_SICK_LEAVE_PATIENT = "Services/Patients.svc/REST/GetPatientSickLeave"; -const GET_MY_OUT_PATIENT = - "Services/DoctorApplication.svc/REST/GetMyOutPatient"; - -const PATIENT_MEDICAL_REPORT_GET_LIST = - "Services/Patients.svc/REST/DAPP_ListMedicalReport"; -const PATIENT_MEDICAL_REPORT_GET_TEMPLATE = - "Services/Patients.svc/REST/DAPP_GetTemplateByID"; -const PATIENT_MEDICAL_REPORT_INSERT = - "Services/Patients.svc/REST/DAPP_InsertMedicalReport"; -const PATIENT_MEDICAL_REPORT_VERIFIED = - "Services/Patients.svc/REST/DAPP_VerifiedMedicalReport"; - -const GET_PROCEDURE_TEMPLETE = - 'Services/Doctors.svc/REST/DAPP_ProcedureTemplateGet'; - -const GET_TEMPLETE_LIST = 'Services/Doctors.svc/REST/DAPP_TemplateGet'; - -const GET_PROCEDURE_TEMPLETE_DETAILS = - "Services/Doctors.svc/REST/DAPP_ProcedureTemplateDetailsGet"; -const GET_PENDING_PATIENT_ER_FOR_DOCTOR_APP = - 'Services/DoctorApplication.svc/REST/GetPendingPatientERForDoctorApp'; - -const DOCTOR_CHECK_HAS_LIVE_CARE = - "Services/DoctorApplication.svc/REST/CheckDoctorHasLiveCare"; - -const LIVE_CARE_IS_LOGIN = "LiveCareApi/DoctorApp/UseIsLogin"; -const ADD_REFERRED_REMARKS_NEW = - "Services/DoctorApplication.svc/REST/AddReferredDoctorRemarks_New"; -const GET_SPECIAL_CLINICAL_CARE_LIST = - "Services/DoctorApplication.svc/REST/GetSpecialClinicalCareList"; -const GET_SPECIAL_CLINICAL_CARE_MAPPING_LIST = - "Services/DoctorApplication.svc/REST/GetSpecialClinicalCareMappingList"; - -const INSERT_MEDICAL_REPORT = - "Services/Patients.svc/REST/DAPP_InsertMedicalReport_New"; - -const UPDATE_MEDICAL_REPORT = - "Services/Patients.svc/REST/DAPP_UpdateMedicalReport"; -const GET_SICK_LEAVE_DOCTOR_APP = - "Services/DoctorApplication.svc/REST/GetAllSickLeaves"; -const ADD_PATIENT_TO_DOCTOR = "LiveCareApi/DoctorApp/AssignPatientToDoctor"; -const REMOVE_PATIENT_FROM_DOCTOR = "LiveCareApi/DoctorApp/BackPatientToQueue"; -const CREATE_DOCTOR_RESPONSE = - "Services/DoctorApplication.svc/REST/CreateDoctorResponse"; -const GET_DOCTOR_NOT_REPLIED_COUNTS = - "Services/DoctorApplication.svc/REST/DoctorApp_GetDoctorNotRepliedCounts"; -const ALL_SPECIAL_LAB_RESULT = - "services/Patients.svc/REST/GetPatientLabSpecialResultsALL"; -const GET_MEDICATION_FOR_IN_PATIENT = - "Services/DoctorApplication.svc/REST/Doctor_GetMedicationForInpatient"; -const GET_EPISODE_FOR_INPATIENT = - "/Services/DoctorApplication.svc/REST/DoctorApp_GetEpisodeForInpatient"; - -///Operation Details Services - -const GET_RESERVATIONS = - "Services/DoctorApplication.svc/REST/DoctorApp_GetReservationDetails"; -const GET_OPERATION_DETAILS = - "Services/DoctorApplication.svc/REST/DoctorApp_GetOperationDetails"; -const UPDATE_OPERATION_REPORT = - "Services/DoctorApplication.svc/REST/DoctorApp_CreateUpdateOperationReport"; - -const NURSING_PROGRESS_NOTE = - "Services/DoctorApplication.svc/REST/DoctorApp_GetNursingProgressNote"; -const GET_DIAGNOSIS_FOR_IN_PATIENT = - "Services/DoctorApplication.svc/REST/DoctorApp_GetDiagnosisForInPatient"; - -const GET_DIABETIC_CHART_VALUES = - "Services/DoctorApplication.svc/REST/DoctorApp_GetDiabeticChartValues"; - -const GET_PENDING_ORDERS = - "Services/DoctorApplication.svc/REST/DoctorApp_GetPendingOrdersForInPatient"; - -const GET_ADMISSION_ORDERS = - "/Services/DoctorApplication.svc/REST/DoctorApp_GetAdmissionOrders"; - -///Patient Registration Services -const CHECK_PATIENT_FOR_REGISTRATION = - "Services/Authentication.svc/REST/CheckPatientForRegisteration"; -const SEND_ACTIVATION_CODE_BY_OTP_NOT_TYPE_FOR_REGISTRATION = - "Services/Authentication.svc/REST/SendActivationCodebyOTPNotificationTypeForRegistration"; -const CHECK_ACTIVATION_CODE_FOR_PATIENT = - "Services/Authentication.svc/REST/CheckActivationCode"; -const PATIENT_REGISTRATION = - "Services/Authentication.svc/REST/PatientRegistration"; -const GET_PATIENT_INFO = "Services/NHIC.svc/REST/GetPatientInfo"; - -/// Discharge Summary -const GET_PENDING_DISCHARGE_SUMMARY = - "Services/DoctorApplication.svc/REST/DoctorApp_GetPendingDischargeSummary"; -const GET_ALL_DISCHARGE_SUMMARY = - "Services/DoctorApplication.svc/REST/DoctorApp_GetDischargeSummary"; - -const VTE_ASSESSMENT = - "Services/Patients.svc/REST/INP_GetVTEHistoryByTransactionNo"; - -const GET_INTERVENTION_MEDICATION = - "Services/DoctorApplication.svc/REST/DoctorApp_GetInterventionMedications"; - -const GET_INTERVENTION_MEDICATION_HISTORY = - "Services/DoctorApplication.svc/REST/DoctorApp_GetInterventionHistory"; - -const SET_ACCEPTED_OR_REJECTED = - "Services/DoctorApplication.svc/REST/DoctorApp_AcceptOrRejectIntervention"; - -const GET_STP_MASTER_LIST = - "Services/DoctorApplication.svc/REST/DoctorApp_GetSTPMasterList"; - -var selectedPatientType = 1; - -//*********change value to decode json from Dropdown ************ -var SERVICES_PATIANT = [ - "GetMyOutPatient", - "GetMyInPatient", - "GtMyDischargePatient", - "GtMyReferredPatient", - "GtMyDischargeReferralPatient", - "GtMyTomorrowPatient", - "GtMyReferralPatient", - "PatientArrivalList" -]; -var SERVICES_PATIANT2 = [ - "List_MyOutPatient", - "List_MyInPatient", - "List_MyDischargePatient", - "List_MyReferredPatient", - "List_MyDischargeReferralPatient", - "List_MyTomorrowPatient", - "List_MyReferralPatient", - "patientArrivalList" -]; -var SERVICES_PATIANT_HEADER = [ - "My OutPatient", - "My InPatient", - "Discharge", - "Referred", - "Referral Discharge", - "Tomorrow", - "Referral", - "Arrival Patient" -]; -var SERVICES_PATIANT_HEADER_AR = [ - "المريض الخارجي", - "المريض المنوم", - "المريض المعافى", - "المريض المحول الي", - "المريض المحال المعافى", - "مريض الغد", - "المريض المحول مني", - "المريض الواصل" -]; - -const PRIMARY_COLOR = 0xff515B5D; - -const TRANSACTION_NO = 0; -const LANGUAGE_ID = 2; -const STAMP = '2020-04-27T12:17:17.721Z'; -const IP_ADDRESS = '9.9.9.9'; -const VERSION_ID = 6.7; -const CHANNEL = 9; -const SESSION_ID = 'BlUSkYymTt'; -const IS_LOGIN_FOR_DOCTOR_APP = true; -const PATIENT_OUT_SA = false; -const IS_DENTAL_ALLOWED_BACKEND = false; -const PATIENT_OUT_SA_PATIENT_REQ = 0; -const SETUP_ID = '91877'; -const GENERAL_ID = 'Cs2020@2016\$2958'; -const PATIENT_TYPE = 1; -const PATIENT_TYPE_ID = 1; /// Timer Info @@ -452,10 +15,12 @@ const TIMER_MIN = 10; class AppGlobal { static var CONTEX; - static Color appRedColor = Color(0xFFD02127); - static Color appGreenColor = Color(0xFF359846); - static Color appTextColor = Color(0xFF2B353E); - static Color scheduleTextColor = Color(0xFF2E303A); - static Color inProgressColor = Color(0xFFCC9B14); + static Color appRedColor = const Color(0xFFD02127); + static Color appGreenColor = const Color(0xFF359846); + static Color appTextColor = const Color(0xFF2B353E); + static Color scheduleTextColor = const Color(0xFF2E303A); + static Color inProgressColor = const Color(0xFFCC9B14); + static Color appGreyColor = const Color(0xFF575757); + static Color appLightGreyColor = const Color(0xFFE6E6E6); } diff --git a/lib/core/config/localized_values.dart b/lib/core/config/localized_values.dart index 4225ed6..12a25a4 100644 --- a/lib/core/config/localized_values.dart +++ b/lib/core/config/localized_values.dart @@ -211,7 +211,7 @@ const Map> localizedValues = { "producerName": {"en": "PRODUCER NAME", "ar": "اسم المنتج"}, "receiptOn": {"en": "RECEIPT ON", "ar": "تاريخ الاستلام"}, "approvalNo": {"en": "Approval No:", "ar": "رقم الموافقة:"}, - "doctor": {"en": "Doctor", "ar": "الدكتور"}, + "Doctor": {"en": "Doctor", "ar": "الدكتور"}, "ext": {"en": "Ext#", "ar": "رقم التحويلة"}, "veryUrgent": {"en": "Very Urgent", "ar": "عاجل جدا"}, "urgent": {"en": "Urgent", "ar": "عاجل"}, @@ -307,7 +307,7 @@ const Map> localizedValues = { "ar": "معلومات السجل الصحي" }, "prevoius-sickleave-issed": { - "en": "Total previous sick leave issued by the doctor", + "en": "Total previous sick leave issued by the Doctor", "ar": "مجموع الإجازات المرضية السابقة التي أصدرها الطبيب" }, "clinicSelect": {"en": "Select Clinic", "ar": "اختر عيادة"}, diff --git a/lib/core/config/size_config.dart b/lib/core/config/size_config.dart index 681bf61..f2fcf56 100644 --- a/lib/core/config/size_config.dart +++ b/lib/core/config/size_config.dart @@ -67,14 +67,14 @@ class SizeConfig { heightMultiplier = _blockHeight; widthMultiplier = _blockWidth; - print('realScreenWidth $realScreenWidth'); - print('realScreenHeight $realScreenHeight'); - print('textMultiplier $textMultiplier'); - print('imageSizeMultiplier $imageSizeMultiplier'); - print('heightMultiplier$heightMultiplier'); - print('widthMultiplier $widthMultiplier'); - print('isPortrait $isPortrait'); - print('isMobilePortrait $isMobilePortrait'); + // print('realScreenWidth $realScreenWidth'); + // print('realScreenHeight $realScreenHeight'); + // print('textMultiplier $textMultiplier'); + // print('imageSizeMultiplier $imageSizeMultiplier'); + // print('heightMultiplier$heightMultiplier'); + // print('widthMultiplier $widthMultiplier'); + // print('isPortrait $isPortrait'); + // print('isMobilePortrait $isMobilePortrait'); } static getTextMultiplierBasedOnWidth({double width}) { diff --git a/lib/core/enum/font_enum.dart b/lib/core/enum/font_enum.dart new file mode 100644 index 0000000..8852b2e --- /dev/null +++ b/lib/core/enum/font_enum.dart @@ -0,0 +1,6 @@ +enum FontType { + Poppins_Bold, + poppins_Medium, + poppins_Regular, + poppins_SemiBold, +} \ No newline at end of file diff --git a/lib/core/response_model/patient_call.dart b/lib/core/response_model/patient_call.dart new file mode 100644 index 0000000..dc1332b --- /dev/null +++ b/lib/core/response_model/patient_call.dart @@ -0,0 +1,87 @@ +import 'dart:math'; + +import 'package:queuing_system/utils/call_type.dart'; + +class Tickets { + Tickets({ + this.callNo, + this.roomNo, + this.callType, + this.createdON, + this.doctorName, + this.doctorNameN, + this.editedON, + this.mobileNo, + this.patientGender, + this.patientID, + this.callNoStr, + this.queueNo, + }); + + int getRandomNum() { + return Random().nextInt(1); + } + + Tickets.fromJson(dynamic json) { + id = json['ID']; + callNo = json['CallNo']; + roomNo = json['RoomNo']; + callType = json['callType']; + createdON = json['CreatedON']; + doctorName = json['DoctorName']; + doctorNameN = json['DoctorNameN']; + editedON = json['EditedON']; + mobileNo = json['MobileNo']; + patientGender = json['PatientGender']; + patientID = json['PatientID']; + queueNo = json['QueueNo']; + callNoStr = json['CallNoStr'] ?? json['CallNo'].toString(); + isAcknowledged = getRandomNum(); + } + + int id; + int callNo; + String roomNo; + int callType; + String createdON; + String doctorName; + String doctorNameN; + String editedON; + String mobileNo; + int patientGender; + int patientID; + String queueNo; + String callNoStr; + bool callUpdated = false; + int isAcknowledged; + + Map toJson() { + final map = {}; + map['ID'] = id; + map['CallNo'] = callNo; + map['RoomNo'] = roomNo; + map['callType'] = callType; + map['CreatedON'] = createdON; + map['DoctorName'] = doctorName; + map['DoctorNameN'] = doctorNameN; + map['EditedON'] = editedON; + map['MobileNo'] = mobileNo; + map['PatientGender'] = patientGender; + map['PatientID'] = patientID; + map['CallNoStr'] = callNoStr; + map['QueueNo'] = queueNo; + return map; + } + + @override + String toString() { + return (callNoStr).toString(); + } + + CallType getCallType() { + if (callType == 0) return CallType.RECEPTION; + if (callType == 1) return CallType.NURSE; + if (callType == 2) return CallType.DOCTOR; + return CallType.NONE; + } +} diff --git a/lib/core/response_model/xyz.dart b/lib/core/response_model/xyz.dart new file mode 100644 index 0000000..11e0cb5 --- /dev/null +++ b/lib/core/response_model/xyz.dart @@ -0,0 +1,59 @@ +import 'dart:convert'; +Xyz xyzFromJson(String str) => Xyz.fromJson(json.decode(str)); +String xyzToJson(Xyz data) => json.encode(data.toJson()); +class Xyz { + Xyz({ + this.callNo, + this.roomNo, + this.callType, + this.createdON, + this.doctorName, + this.doctorNameN, + this.editedON, + this.mobileNo, + this.patientGender, + this.patientID, + this.queueNo,}); + + Xyz.fromJson(dynamic json) { + callNo = json['CallNo']; + roomNo = json['RoomNo']; + callType = json['CallType']; + createdON = json['CreatedON']; + doctorName = json['DoctorName']; + doctorNameN = json['DoctorNameN']; + editedON = json['EditedON']; + mobileNo = json['MobileNo']; + patientGender = json['PatientGender']; + patientID = json['PatientID']; + queueNo = json['QueueNo']; + } + int callNo; + String roomNo; + int callType; + String createdON; + String doctorName; + String doctorNameN; + String editedON; + String mobileNo; + int patientGender; + int patientID; + String queueNo; + + Map toJson() { + final map = {}; + map['CallNo'] = callNo; + map['RoomNo'] = roomNo; + map['CallType'] = callType; + map['CreatedON'] = createdON; + map['DoctorName'] = doctorName; + map['DoctorNameN'] = doctorNameN; + map['EditedON'] = editedON; + map['MobileNo'] = mobileNo; + map['PatientGender'] = patientGender; + map['PatientID'] = patientID; + map['QueueNo'] = queueNo; + return map; + } + +} \ No newline at end of file diff --git a/lib/header/app_header.dart b/lib/header/app_header.dart index e69de29..4cae3c2 100644 --- a/lib/header/app_header.dart +++ b/lib/header/app_header.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:queuing_system/core/config/config.dart'; +import 'package:queuing_system/utils/utils.dart'; +import 'package:queuing_system/widget/data_display/app_texts_widget.dart'; + +class AppHeader extends StatelessWidget with PreferredSizeWidget { + @override + Widget build(BuildContext context) { + + return Container( + padding: const EdgeInsets.only( + left: 0, + right: 5, + ), + decoration: BoxDecoration( + color: AppGlobal.appRedColor, border: const Border(bottom: BorderSide(color: Color(0xFFEFEFEF)))), + child: Container( + height: 100, + padding: const EdgeInsets.only(left: 20, right: 20, bottom: 0,), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + AppText( + " Current Serving", + color: Colors.white, + fontFamily: 'Poppins-SemiBold.ttf', + + ), + SvgPicture.asset( "assets/images/hmglogo.svg", height: Utils.getHeight() * 0.5,), + ], + ), + ), + ); + } + + @override + Size get preferredSize => Size( + double.maxFinite, + Utils.getHeight()); +} diff --git a/lib/home/first_column.dart b/lib/home/first_column.dart new file mode 100644 index 0000000..f99e8eb --- /dev/null +++ b/lib/home/first_column.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:queuing_system/core/config/size_config.dart'; +import 'package:queuing_system/home/que_item/que_item.dart'; + +class FirstColumn extends StatelessWidget { + final bool have3Patient; + final bool have2Patient; + + const FirstColumn({Key key, this.have3Patient = false, this.have2Patient = false}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const TicketItem(queNo: "OBG-T45", isFirstLine: true, isNurseVisit: true, haveListOfPatient: true,), + SizedBox( + height: SizeConfig.getHeightMultiplier() * 5,), + if(have3Patient ||have2Patient ) + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + if(have2Patient || have3Patient) + const TicketItem(queNo: "OBG-T45", isSecondLine: true, isNurseVisit: false, haveListOfPatient: true,), + if(have3Patient) + const TicketItem(queNo: "OBG-T45", isSecondLine: true, isNurseVisit: true, haveListOfPatient: true,), + ], + ), + ], + ); + } +} diff --git a/lib/home/home_screen.dart b/lib/home/home_screen.dart index 3cc43af..fc03b41 100644 --- a/lib/home/home_screen.dart +++ b/lib/home/home_screen.dart @@ -1,34 +1,254 @@ +import 'dart:developer'; + +import 'package:connectivity/connectivity.dart'; import 'package:flutter/material.dart'; +import 'package:queuing_system/core/api.dart'; import 'package:queuing_system/core/base/app_scaffold_widget.dart'; +import 'package:queuing_system/core/config/config.dart'; +import 'package:queuing_system/core/config/size_config.dart'; +import 'package:queuing_system/core/response_model/patient_call.dart'; +import 'package:queuing_system/header/app_header.dart'; +import 'package:queuing_system/home/home_screen_components.dart'; +import 'package:queuing_system/utils/call_by_voice.dart'; +import 'package:queuing_system/utils/call_type.dart'; import 'package:queuing_system/utils/signalR_utils.dart'; +import 'package:queuing_system/utils/utils.dart'; +import 'package:queuing_system/widget/data_display/app_texts_widget.dart'; -class MyHomePage extends StatefulWidget { +var DEVICE_IP = "10.10.15.11"; // Testing IP +// var DEVICE_IP = "10.10.14.11"; // Testing IP +// var DEVICE_IP = "10.10.15.11"; +// var DEVICE_IP = "10.70.249.21"; // (Make sure by Haroon before use it) Production IP - String title ="MyHomePage"; +class MyHomePage extends StatefulWidget { + String title = "MyHomePage"; @override State createState() => _MyHomePageState(); } class _MyHomePageState extends State { + SignalRHelper signalRHelper = SignalRHelper(); + + List waitings = []; + List currents = []; + + bool isLoading = false; + + @override + void dispose() { + super.dispose(); + } + + @override + void initState() { + listenNetworkConnectivity(); + + if (!signalRHelper.getConnectionState()) { + signalRHelper.startSignalRConnection(DEVICE_IP, onUpdateAvailable: onUpdateAvailable, onConnect: onConnect, onConnecting: onConnecting, onDisconnect: onDisconnect); + } + + super.initState(); + } + + TextEditingController controller = TextEditingController(); + @override Widget build(BuildContext context) { - SignalRHelper signalRHelper= SignalRHelper(); return AppScaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - signalRHelper.msg, + appBar: AppHeader(), + body: content(), + bottomNavigationBar: Container( + color: Colors.grey.withOpacity(0.1), + height: Utils.getHeight(), + width: double.infinity, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + const SizedBox(width: 20), + AppText( + "Powered By", + fontSize: SizeConfig.getWidthMultiplier() * 2.6, + fontFamily: 'Poppins-Medium.ttf', + ), + const SizedBox(width: 20), + Image.asset( + "assets/images/cloud_logo.png", + height: SizeConfig.getHeightMultiplier() * 4, + ), + ], + ), + Row( + children: [ + const SizedBox(width: 60), + SizedBox( + width: 200, + child: TextField( + controller: controller, + )), + const SizedBox(width: 30), + isLoading + ? const CircularProgressIndicator() + : ElevatedButton( + onPressed: onUpdateIPPressed, + child: const Text( + "Update IP", + style: TextStyle(color: Colors.white), + ), + style: ElevatedButton.styleFrom(backgroundColor: AppGlobal.appRedColor), + ), + const SizedBox(width: 30), + Text("IP: $DEVICE_IP", style: const TextStyle(fontWeight: FontWeight.w600)), + const SizedBox(width: 20), + ], ), ], ), - ), // This trailing comma makes auto-formatting nicer for build methods. + ), ); } + + onUpdateIPPressed() async { + if (controller.text.isNotEmpty) { + isLoading = true; + setState(() {}); + DEVICE_IP = controller.text; + + await signalRHelper.connection.stop(); + if (!signalRHelper.getConnectionState()) { + await signalRHelper.startSignalRConnection(DEVICE_IP, onUpdateAvailable: onUpdateAvailable, onConnect: onConnect, onConnecting: onConnecting, onDisconnect: onDisconnect); + } + + controller.clear(); + waitings.clear(); + isLoading = false; + setState(() {}); + } + } + + Widget content() { + // waitings = waitings.sublist(0,3); + voiceCall(); + + if (waitings.isEmpty) { + // No Patient in Queue + return noPatientInQueue(); + } else if (waitings.length > 4) { + // Return Content With Side List + return priorityTicketsWithSideList(waitings); + } else { + // Return Content In Center Aligned + return priorityTickets(waitings); + } + } + + String getCallTypeText(Tickets ticket) { + final callType = ticket.getCallType(); + switch (callType) { + case CallType.RECEPTION: + return "Please Visit Doctor"; + break; + case CallType.NURSE: + return "Please Visit Nurse"; + break; + case CallType.DOCTOR: + return "Please Visit Doctor"; + break; + case CallType.NONE: + return ""; + break; + default: + return ""; + } + } + + CallByVoice voiceCaller; + + voiceCall() async { + var j = { + "ID": 4182, + "PatientID": 123123, + "MobileNo": "05***6794", + "DoctorName": "Shakiera", + "DoctorNameN": "Shakeria", + "PatientGender": 1, + "CallNo": 123, + "callType": 1, + "RoomNo": "10", + "CreatedOn": "/Date(1673771382130+0300)/", + "EditedOn": "/Date(1673771384500+0300)/", + "CallNoStr": "A-5", + "QueueNo": null + }; + waitings = [Tickets.fromJson(j)]; + + if (waitings.isNotEmpty && voiceCaller == null) { + final postVoice = getCallTypeText(waitings.first); + voiceCaller = CallByVoice(waitings.first.callNoStr.toString(), preVoice: "Ticket Number", postVoice: postVoice, lang: 'en'); + await voiceCaller.startCalling(); + voiceCaller = null; + } + } + + + onUpdateAvailable(data) async { + waitings.clear(); + API.getCallRequestInfoByClinicInfo(DEVICE_IP, onSuccess: (waitingCalls) { + setState(() { + waitings = waitingCalls; + // currents = currentInClinic; + }); + + log("\n\n"); + log("--------------------"); + log("waiting: $waitings"); + log("--------------------"); + log("\n\n"); + + updateTickets(); + }, onFailure: (error) {}); + } + + updateTickets() { + if (waitings != null && waitings.isNotEmpty) { + List _ticketsToUpdate = waitings.where((t) => t.callUpdated == false).toList(); + API.callUpdateNotIsQueueRecordByIDAsync(DEVICE_IP, ticket: _ticketsToUpdate.first, onSuccess: (tickets_updated) { + log("[${tickets_updated.length}] Tickets Updated: $tickets_updated"); + }, onFailure: (e) { + log("API UPDate Tickets Failed with : ${e.toString()}"); + }); + } + } + + onConnect() { + log("SignalR: onConnect"); + } + + onDisconnect(exception) { + log("SignalR: onDisconnect"); + // signalRHelper.startSignalRConnection(DEVICE_IP, onUpdateAvailable: onUpdateAvailable, onConnect: onConnect, onConnecting: onConnecting, onDisconnect: onDisconnect); + } + + onConnecting() { + log("SignalR: onConnecting"); + } + + listenNetworkConnectivity() async { + Connectivity().onConnectivityChanged.listen((event) { + switch (event) { + case ConnectivityResult.wifi: + signalRHelper.connection.start(); + break; + case ConnectivityResult.none: + signalRHelper.closeConnection(context); + break; + case ConnectivityResult.mobile: + break; + } + }); + } } diff --git a/lib/home/home_screen_bkp.dart b/lib/home/home_screen_bkp.dart new file mode 100644 index 0000000..e0ad7bc --- /dev/null +++ b/lib/home/home_screen_bkp.dart @@ -0,0 +1,205 @@ +// import 'dart:async'; +// import 'package:flutter/material.dart'; +// import 'package:queuing_system/core/api.dart'; +// import 'package:queuing_system/core/base/app_scaffold_widget.dart'; +// import 'package:queuing_system/core/base/base_app_client.dart'; +// import 'package:queuing_system/core/config/config.dart'; +// import 'package:queuing_system/core/config/size_config.dart'; +// import 'package:queuing_system/header/app_header.dart'; +// import 'package:queuing_system/home/que_item_list.dart'; +// import 'package:queuing_system/utils/signalR_utils.dart'; +// import 'package:queuing_system/utils/utils.dart'; +// import 'package:queuing_system/widget/data_display/app_texts_widget.dart'; +// import 'first_column.dart'; +// +// +// var DEVICE_IP = "10.70.249.21"; +// +// class MyHomePage extends StatefulWidget { +// String title = "MyHomePage"; +// bool have0Patient = true; +// bool have1Patient = false; +// bool have2Patient = false; +// bool have3Patient = false; +// bool haveListOfPatient = false; +// +// @override +// State createState() => _MyHomePageState(); +// } +// +// class _MyHomePageState extends State { +// Timer _timer; +// int remainingTime = 30; +// +// @override +// void dispose() { +// _timer.cancel(); +// super.dispose(); +// } +// +// startTimer() { +// Timer.periodic(const Duration(seconds: 1), (timer) { +// if (remainingTime == 0) { +// setState(() { +// remainingTime = 30; +// }); +// } else { +// setState(() { +// remainingTime--; +// if (remainingTime > 25) { +// +// /// for 0 patinet +// widget.have0Patient = true; +// widget.have1Patient = false; +// widget.have2Patient = false; +// widget.have3Patient = false; +// widget.haveListOfPatient = false; +// } else if (remainingTime > 20) { +// /// for 1 patinet +// +// widget.have0Patient = false; +// widget.have1Patient = true; +// widget.have2Patient = false; +// widget.have3Patient = false; +// widget.haveListOfPatient = false; +// } else if (remainingTime > 15) { +// +// /// for 2 patinet +// +// widget.have0Patient = false; +// widget.have1Patient = false; +// widget.have2Patient = true; +// widget.have3Patient = false; +// widget.haveListOfPatient = false; +// } else if (remainingTime > 10) { +// /// for 3 only patinet +// widget.have0Patient = false; +// widget.have1Patient = false; +// widget.have2Patient = false; +// widget.have3Patient = true; +// widget.haveListOfPatient = false; +// } else { +// /// for 3+ only patinet +// +// widget.have0Patient = false; +// widget.have1Patient = false; +// widget.have2Patient = false; +// widget.have3Patient = true; +// widget.haveListOfPatient = true; +// } +// }); +// } +// }); +// } +// +// @override +// void initState() { +// startTimer(); +// // Get Ticket Info +// // http://10.200.204.11:2222/Services/Nurses.svc/REST/GetCallRequestInfoByClinincInfo +// +// SignalRHelper signalRHelper = SignalRHelper(); +// if (!signalRHelper.getConnectionState()) { +// signalRHelper.startSignalRConnection(DEVICE_IP, onUpdateAvailable: onUpdateAvailable); +// } +// super.initState(); +// } +// +// @override +// Widget build(BuildContext context) { +// +// +// return AppScaffold( +// appBar: AppHeader(), +// body: Column( +// children: [ +// SizedBox( +// height: SizeConfig.getHeightMultiplier() * +// (widget.haveListOfPatient +// ? 2 +// : widget.have1Patient || widget.have0Patient +// ? 20 +// : 10)), +// widget.have0Patient +// ? Column( +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// Center( +// child: AppText("Awaiting Patients Arrival", +// fontFamily: 'Poppins-SemiBold.ttf', +// fontSize: SizeConfig.getWidthMultiplier() * 9), +// ), +// ], +// ) +// : widget.haveListOfPatient +// ? Row( +// children: [ +// FirstColumn( +// have3Patient: widget.have3Patient, +// have2Patient: widget.have2Patient, +// ), +// const SizedBox( +// width: 40, +// ), +// if (widget.haveListOfPatient) +// Container( +// width: 10, +// height: SizeConfig.getHeightMultiplier() * 40, +// color: AppGlobal.appLightGreyColor, +// ), +// if (widget.haveListOfPatient) +// const SizedBox( +// width: 40, +// ), +// if (widget.haveListOfPatient) const QueItemList() +// ], +// ) +// : FirstColumn( +// have3Patient: widget.have3Patient, +// have2Patient: widget.have2Patient, +// ), +// ], +// ), +// bottomSheet: Container( +// color: Colors.transparent, +// height: Utils.getHeight(), +// width: double.infinity, +// child: Row( +// children: [ +// Padding( +// padding: const EdgeInsets.only(top: 30, left: 30), +// child: AppText( +// "Powered By", +// fontSize: SizeConfig.getWidthMultiplier() * 2.6, +// fontFamily: 'Poppins-Medium.ttf', +// ), +// ), +// Padding( +// padding: const EdgeInsets.only(top: 40, left: 18), +// child: Image.asset( +// "assets/images/cloud_logo.png", +// height: SizeConfig.getHeightMultiplier() * 6, +// ), +// ), +// ], +// ), +// ), // This trailing comma makes auto-formatting nicer for build methods. +// ); +// } +// +// +// onUpdateAvailable(data) async{ +// API.GetCallRequestInfoByClinincInfo( +// DEVICE_IP, +// onSuccess: (waitingCalls, currentInClinic){ +// print("\n\n"); +// print("--------------------"); +// print("Current: $currentInClinic"); +// print("Waiting: $waitingCalls"); +// print("--------------------"); +// print("\n\n"); +// }, onFailure: (error){ +// +// }); +// } +// } diff --git a/lib/home/home_screen_components.dart b/lib/home/home_screen_components.dart new file mode 100644 index 0000000..3f3408f --- /dev/null +++ b/lib/home/home_screen_components.dart @@ -0,0 +1,98 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:queuing_system/core/config/size_config.dart'; +import 'package:queuing_system/core/response_model/patient_call.dart'; +import 'package:queuing_system/home/priority_calls.dart'; +import 'package:queuing_system/utils/call_type.dart'; +import 'package:queuing_system/widget/data_display/app_texts_widget.dart'; + +Widget noPatientInQueue() { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Center( + child: AppText("Awaiting Patients Arrival", fontFamily: 'Poppins-SemiBold.ttf', fontSize: SizeConfig.getWidthMultiplier() * 9), + ), + ], + ); +} + +Widget priorityTickets(List tickets) { + return PriorityTickets(tickets); +} + +Widget priorityTicketsWithSideList(List tickets) { + final priorityTickets = tickets.sublist(0, 3); + final otherTickets = tickets.sublist(3, tickets.length); + return Row( + children: [ + Expanded(flex: 2, child: PriorityTickets(priorityTickets)), + Container(color: Colors.grey.withOpacity(0.1), width: 10, margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 50)), + Expanded( + flex: 2, + child: ListView.builder( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 50), + itemCount: otherTickets.length, + itemBuilder: (ctx, idx) { + final itm = otherTickets[idx]; + + return Padding( + padding: const EdgeInsets.all(8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + width: SizeConfig.getWidthMultiplier() * 13, + child: AppText( + itm.callNoStr.toString(), + letterSpacing: -2.32, + fontWeight: FontWeight.bold, + fontSize: SizeConfig.getWidthMultiplier() * 4.5, + textAlign: TextAlign.end, + ), + ), + const SizedBox(width: 10), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + SizedBox( + width: SizeConfig.getWidthMultiplier() * 3.3, + child: itm.getCallType().icon(SizeConfig.getHeightMultiplier() * 2.5), + ), + const SizedBox(width: 10), + SizedBox( + width: SizeConfig.getWidthMultiplier() * 29, + child: AppText( + itm.getCallType().message('en'), + color: itm.getCallType().color(), + letterSpacing: -1.5, + fontSize: SizeConfig.getWidthMultiplier() * 3.3, + fontWeight: FontWeight.w600, + fontHeight: 0.5, + ), + ), + Container( + color: Colors.grey.withOpacity(0.3), + width: 6, + height: SizeConfig.getHeightMultiplier() * 3, + margin: const EdgeInsets.symmetric(horizontal: 10), + ), + AppText( + "Room: ${itm.roomNo}", + color: itm.getCallType().color(), + letterSpacing: -1.5, + fontSize: SizeConfig.getWidthMultiplier() * 3.3, + fontWeight: FontWeight.w600, + fontHeight: 0.5, + ), + ], + ) + ], + ), + ); + }, + ), + ) + ], + ); +} diff --git a/lib/home/priority_calls.dart b/lib/home/priority_calls.dart new file mode 100644 index 0000000..35ae16b --- /dev/null +++ b/lib/home/priority_calls.dart @@ -0,0 +1,118 @@ +import 'package:blinking_text/blinking_text.dart'; +import 'package:flutter/material.dart'; +import 'package:queuing_system/core/config/size_config.dart'; +import 'package:queuing_system/core/response_model/patient_call.dart'; +import 'package:queuing_system/utils/call_type.dart'; +import 'package:queuing_system/widget/data_display/app_texts_widget.dart'; + +class PriorityTickets extends StatelessWidget { + List tickets; + + PriorityTickets(this.tickets, {Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final firstTicket = tickets[0]; + final otherTickets = tickets.sublist(1, tickets.length); + + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 20), + vTicketItem( + ticketNo: firstTicket.callNoStr ?? '', + callType: firstTicket.getCallType(), + scale: 1, + blink: true, + roomNo: firstTicket.roomNo, + ), + const SizedBox(height: 40), + if (tickets.length > 1) ...[ + SizedBox(height: SizeConfig.getHeightMultiplier() * 1.5), + Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: otherTickets + .map((ticket) => Padding( + padding: EdgeInsets.only(top: SizeConfig.getHeightMultiplier() * 2), + child: vTicketItem( + ticketNo: ticket.callNoStr ?? '', + callType: ticket.getCallType(), + scale: 0.7, + roomNo: ticket.roomNo, + ), + )) + .toList(), + ) + ] + ], + ); + } +} + +class vTicketItem extends StatelessWidget { + final String ticketNo; + final String roomNo; + final CallType callType; + final bool blink; + final double scale; + + const vTicketItem({@required this.ticketNo, @required this.roomNo, @required this.callType, this.scale, this.blink = false}); + + @override + Widget build(BuildContext context) { + return Transform.scale( + scale: scale, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + BlinkText(ticketNo, + style: TextStyle(fontSize: SizeConfig.getWidthMultiplier() * 10, letterSpacing: -9.32, height: 0.5, fontWeight: FontWeight.bold), + beginColor: Colors.black, + endColor: blink ? Colors.black.withOpacity(0.1) : Colors.black, + // endColor: blink ? AppGlobal.appRedColor : Colors.black, + times: 0, + duration: const Duration(seconds: 1)), + // AppText( + // ticketNo, + // letterSpacing: -9.32, + // fontSize: SizeConfig.getWidthMultiplier() * 16, + // fontWeight: FontWeight.bold, + // fontHeight: 0.7, + // ), + const SizedBox(height: 10), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + callType.icon(SizeConfig.getHeightMultiplier() * 3), + const SizedBox(width: 10), + AppText( + callType.message('en'), + color: callType.color(), + letterSpacing: -1.5, + fontSize: SizeConfig.getWidthMultiplier() * 3.8, + fontWeight: FontWeight.w600, + fontHeight: 0.5, + ), + Container( + color: Colors.grey.withOpacity(0.3), + width: 6, + height: SizeConfig.getHeightMultiplier() * 3, + margin: const EdgeInsets.symmetric(horizontal: 10), + ), + AppText( + "Room: $roomNo", + color: callType.color(), + letterSpacing: -1.5, + fontSize: SizeConfig.getWidthMultiplier() * 3.8, + fontWeight: FontWeight.w600, + fontHeight: 0.5, + ), + ], + ), + ], + ), + ); + } +} diff --git a/lib/home/que_item.dart b/lib/home/que_item.dart deleted file mode 100644 index e69de29..0000000 diff --git a/lib/home/que_item/que_item.dart b/lib/home/que_item/que_item.dart new file mode 100644 index 0000000..68c0454 --- /dev/null +++ b/lib/home/que_item/que_item.dart @@ -0,0 +1,88 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:queuing_system/core/config/config.dart'; +import 'package:queuing_system/core/config/size_config.dart'; +import 'package:queuing_system/home/que_item/que_item_widget.dart'; +import 'package:queuing_system/widget/data_display/app_texts_widget.dart'; + +class TicketItem extends StatelessWidget { + const TicketItem({ + Key key, + this.isFirstLine = false, + this.isSecondLine = false, + this.isInListLine = false, + this.queNo, + this.isNurseVisit = false, + this.idDoctorVisit = false, this.haveListOfPatient + }) : super(key: key); + final bool isFirstLine; + final bool isSecondLine; + final bool isInListLine; + final bool isNurseVisit; + final bool idDoctorVisit; + final String queNo; + final bool haveListOfPatient; + + @override + Widget build(BuildContext context) { + return haveListOfPatient? + Padding( + padding: const EdgeInsets.all(45.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + QueItemWidget( + isFirstLine: isFirstLine, + isNurseVisit: isNurseVisit, + isSecondLine: isSecondLine, + queNo: queNo, + ), + ], + ), + ) + :Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.only(right: 20.0, left: 20.0), + child: AppText( + queNo, + fontSize: SizeConfig.getWidthMultiplier() * + (isFirstLine + ? 13 + : isSecondLine + ? 8.5 + : 4.7), + letterSpacing: -3.26, + fontWeight: FontWeight.w600, + fontFamily: 'Poppins', + ), + ), + const SizedBox(width: 30,), + + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SvgPicture.asset( + isNurseVisit + ? "assets/images/nurseicon.svg" + : "assets/images/doctoricon.svg", height:SizeConfig.getHeightMultiplier()*2.5 ,), + const SizedBox(width: 4,), + AppText( + isNurseVisit ? " Please Visit Nurse" : " Please Visit Doctor", + color: AppGlobal.appGreyColor, + fontSize: SizeConfig.getWidthMultiplier() * (isFirstLine + ? 3.3 + : isSecondLine + ? 3.3 + : 3.3), + letterSpacing: -1.6, + fontFamily: 'Poppins-Medium.ttf', + ), + ], + ) + ], + ); + } +} diff --git a/lib/home/que_item/que_item_widget.dart b/lib/home/que_item/que_item_widget.dart new file mode 100644 index 0000000..f327236 --- /dev/null +++ b/lib/home/que_item/que_item_widget.dart @@ -0,0 +1,67 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:queuing_system/core/config/config.dart'; +import 'package:queuing_system/core/config/size_config.dart'; +import 'package:queuing_system/widget/data_display/app_texts_widget.dart'; + +///TODO Roaa we have dublicated code between this and the que item widget we need to make it customize + +class QueItemWidget extends StatelessWidget { + const QueItemWidget({ + Key key, + this.isFirstLine = false, + this.isSecondLine = false, + this.queNo, + this.isNurseVisit = false, + }) : super(key: key); + final bool isFirstLine; + final bool isSecondLine; + final bool isNurseVisit; + final String queNo; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + AppText( + queNo, + fontSize: SizeConfig.getWidthMultiplier() * + (isFirstLine + ? 14 + : isSecondLine + ? 8.5 + : 5.5), + letterSpacing: -13.72, + fontWeight: FontWeight.bold, + // fontFamily: 'Poppins-Bold.ttf', + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + isNurseVisit + ? "assets/images/nurseicon.svg" + : "assets/images/doctoricon.svg", height:SizeConfig.getHeightMultiplier()*2.5 ,), + const SizedBox(width: 25,), + AppText( + isNurseVisit ? "Please Visit Nurse" : "Please Visit Doctor", + color: isNurseVisit + ? AppGlobal.appGreenColor + : AppGlobal.appRedColor, + fontSize: SizeConfig.getWidthMultiplier() * (isFirstLine + ? 3.3 + : isSecondLine + ? 3.3 + : 3.3), + letterSpacing: -3.25, + fontWeight: FontWeight.w600, + fontFamily: 'Poppins-Medium.ttf', + ), + ], + ), + ], + ); + } +} diff --git a/lib/home/que_item_list.dart b/lib/home/que_item_list.dart index e69de29..5b8d098 100644 --- a/lib/home/que_item_list.dart +++ b/lib/home/que_item_list.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:queuing_system/core/config/size_config.dart'; +import 'package:queuing_system/home/que_item/que_item.dart'; + +class QueItemList extends StatelessWidget { + const QueItemList({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return SizedBox( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: SizeConfig.getHeightMultiplier() *2.3,), + const TicketItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: true, haveListOfPatient: false,), + const TicketItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: true, haveListOfPatient: false,), + const TicketItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: false, haveListOfPatient: false,), + const TicketItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: true, haveListOfPatient: false,), + const TicketItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: true, haveListOfPatient: false,), + const TicketItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: false, haveListOfPatient: false,), + const TicketItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: true, haveListOfPatient: false,), + const TicketItem(queNo: "OBG-T45", isInListLine: true, isNurseVisit: false, haveListOfPatient: false,), + + ],), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index ffcdf1f..0d37e23 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,11 +1,9 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:queuing_system/utils/signalR_utils.dart'; - -import 'core/base/app_scaffold_widget.dart'; import 'core/base/project_view_model.dart'; import 'core/config/size_config.dart'; import 'home/home_screen.dart'; +// import 'home/home_screen_bkp.dart'; void main() { runApp(const MyApp()); @@ -37,7 +35,7 @@ class MyApp extends StatelessWidget { primaryColor: Colors.grey, fontFamily: 'Poppins', dividerColor: Colors.grey[350], - backgroundColor: Color.fromRGBO(255, 255, 255, 1), + backgroundColor: const Color.fromRGBO(255, 255, 255, 1), ), home:MyHomePage() , debugShowCheckedModeBanner: false, diff --git a/lib/utils/call_by_voice.dart b/lib/utils/call_by_voice.dart new file mode 100644 index 0000000..910e82d --- /dev/null +++ b/lib/utils/call_by_voice.dart @@ -0,0 +1,60 @@ +import 'dart:developer'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter_tts/flutter_tts.dart'; + +class CallByVoice { + final String lang; + final String preVoice; + final String ticketNo; + final String postVoice; + + CallByVoice(this.ticketNo, {this.lang = 'en', @required this.preVoice, @required this.postVoice}); + + final FlutterTts textToSpeech = FlutterTts(); + + double volume = 1.0; + double pitch = 0.9; + double rate = 0.5; + + Future _getLanguages() async => await textToSpeech.getLanguages; + + startCalling() async { + log("languages: ${await _getLanguages()}"); + log("no: $ticketNo"); + textToSpeech.setLanguage("en-US"); + var splitText = ticketNo.split("-"); + // Create Pre Voice Players + if (preVoice != null && preVoice.isNotEmpty) { + textToSpeech.setSpeechRate(rate); + textToSpeech.setPitch(pitch); + textToSpeech.setVolume(volume); + await textToSpeech.speak(preVoice + " .. " + splitText[0] + " .. " + splitText[1] + " .. " + postVoice); + } + + // // Create Ticket Number Voice Players + // final characters = ticketNo.characters.toList(); + // for (int i = 0; i < characters.length; i++) { + // final no = characters[i]; + // if (no.isNotEmpty && no != "-" && no != "_" && no != " ") { + // + // await _player.stop(); + // await _player.setAsset('assets/voice_$lang/${no.toUpperCase()}.mp3'); + // await _player.play(); + // } + // } + + // Create Post Voice Players + // if (postVoice != null && postVoice.isNotEmpty) { + // await Future.delayed(const Duration(milliseconds: 1000)); + // + // await _player.stop(); + // await _player.setAsset('assets/voice_$lang/$postVoice'); + // await _player.play(); + // } + } + +// stop() async { +// await _player.stop(); +// } +} diff --git a/lib/utils/call_type.dart b/lib/utils/call_type.dart new file mode 100644 index 0000000..b3cfb99 --- /dev/null +++ b/lib/utils/call_type.dart @@ -0,0 +1,60 @@ +import 'dart:ui'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:queuing_system/core/config/config.dart'; + +enum CallType{ + RECEPTION, + NURSE, + DOCTOR, + NONE, +} + +extension xCallType on CallType{ + + Color color(){ + if(this == CallType.RECEPTION) { + return AppGlobal.appRedColor; + }else if(this == CallType.NURSE) { + return AppGlobal.appGreenColor; + }else if(this == CallType.DOCTOR) { + return AppGlobal.appRedColor ; + }else{ + return Colors.black54; + } + } + + SvgPicture icon(double height,){ + if(this == CallType.RECEPTION) { + return SvgPicture.asset("assets/images/doctoricon.svg", height: height, color: color()); + }else if(this == CallType.NURSE) { + return SvgPicture.asset("assets/images/nurseicon.svg", height: height, color: color()); + }else if(this == CallType.DOCTOR) { + return SvgPicture.asset("assets/images/doctoricon.svg", height: height, color: color()); + } + return SvgPicture.asset("assets/images/wait.svg", height: height, color: color());; + } + + String message(String lang){ + if(this == CallType.RECEPTION) { + return "Please visit reception"; + }else if(this == CallType.NURSE) { + return "Please visit nurse"; + }else if(this == CallType.DOCTOR) { + return "Please visit doctor"; + } + return "Please wait . . ."; + } + + String audio(String lang){ + if(this == CallType.RECEPTION) { + return "visit_doctor.mp3"; + }else if(this == CallType.NURSE) { + return "visit_nurse.mp3"; + }else if(this == CallType.DOCTOR) { + return "visit_doctor.mp3"; + } + return ""; + } +} \ No newline at end of file diff --git a/lib/utils/signalR_utils.dart b/lib/utils/signalR_utils.dart index 7c10276..505feb1 100644 --- a/lib/utils/signalR_utils.dart +++ b/lib/utils/signalR_utils.dart @@ -1,29 +1,81 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; +import 'package:http/io_client.dart'; import 'package:signalr_core/signalr_core.dart'; -class SignalRHelper{ +/* +https://vcallapi.hmg.com/patientcalling.html?IPAddress=10.10.14.20&Clinic=4&Project=15 + +--------------------------------------- + IP, Clinic, Project Mapping to SignalR +--------------------------------------- +(SignalR: 10.10.14.11) <<<< [IP=10.10.14.20 | Clinic=4 | Project=15] +(SignalR: 10.70.249.21) <<<< [IP=10.10.14.20 | Clinic=3 | Project=16] +--------------------------------------- +*/ - String hubBaseURL =""; - String msg ="Elham"; +class SignalRHelper{ + String hubBaseURL = "https://vcallapi.hmg.com/PatientCallingHub"; + // String hubBaseURL = "https://vcallapi.hmg.com/PatientCallingHub?IPAddress=10.10.14.20"; + // "https://VCallApi.hmg.com/WebRTCHub?source=mobile&username=2001273"; + String msg ="Awaiting Patients Arrival"; HubConnection connection; - SignalRHelper(){ + + startSignalRConnection(String deviceIp, {@required Function(dynamic) onUpdateAvailable, @required VoidCallback onConnect, @required Function(dynamic) onDisconnect, @required VoidCallback onConnecting}) async { + + // Hardcoded IP For Testing + // deviceIp = "10.10.14.11"; + print("Connecting Signal R with: $deviceIp"); + + final url = hubBaseURL+"?IPAddress=$deviceIp"; connection = HubConnectionBuilder() .withUrl( - hubBaseURL, + url, HttpConnectionOptions( - logging: (level, message) { - msg = message; - print("$message"); + client: IOClient(HttpClient()..badCertificateCallback = (x, y, z) => true), + transport: HttpTransportType.webSockets, + logging: (level, message) => { + print(message) }, - ) - ).build(); + )) + .build(); + + connection.onclose(onDisconnect); + connection.onreconnecting((exception) => onConnecting()); + connection.onreconnected((connectionId) => onConnect()); + + connection.on('addChatMessage', (message) { + onUpdateAvailable(message); + }); + + await connection.start(); + + } + + void sendMessage(List args) async { + await connection.invoke('SendMessage', args: args); //['Bob', 'Says hi!'] + } + + bool getConnectionState() { + if(connection == null ) return false; + if (connection.state == HubConnectionState.connected || connection.state == HubConnectionState.connecting) return true; + if (connection.state == HubConnectionState.disconnected || connection.state == HubConnectionState.disconnecting) return false; } closeConnection(BuildContext context) async { - if(connection.state == HubConnectionState.connected) + if(connection.state == HubConnectionState.connected || connection.state == HubConnectionState.connecting) { await connection.stop(); } } + + startConnection(BuildContext context) async { + if(connection.state == HubConnectionState.connected || connection.state == HubConnectionState.connecting) + { + connection.off('addChatMessage'); + await connection.start(); + } + } } \ No newline at end of file diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index c585496..cc01d0f 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -176,4 +176,8 @@ class Utils { // Join/Merge all words back to one String return capitalizedWords.join(' '); } + + static getHeight() { + return SizeConfig.getHeightMultiplier()*7; + } } diff --git a/lib/widget/data_display/app_texts_widget.dart b/lib/widget/data_display/app_texts_widget.dart index 90e5986..d4e88d1 100644 --- a/lib/widget/data_display/app_texts_widget.dart +++ b/lib/widget/data_display/app_texts_widget.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:queuing_system/core/config/size_config.dart'; @@ -31,8 +30,8 @@ class AppText extends StatefulWidget { final TextDecoration textDecoration; final bool isCopyable; - AppText( - this.text, { + const AppText( + this.text, {Key key, this.color = Colors.black, this.fontWeight, this.variant, @@ -59,7 +58,7 @@ class AppText extends StatefulWidget { this.textDecoration, this.letterSpacing, this.isCopyable = false, - }); + }) : super(key: key); @override _AppTextState createState() => _AppTextState(); @@ -72,9 +71,9 @@ class _AppTextState extends State { @override void didUpdateWidget(covariant AppText oldWidget) { setState(() { - if (widget.style == "overline") + if (widget.style == "overline") { text = widget.text.toUpperCase(); - else { + } else { text = widget.text; } }); @@ -84,9 +83,9 @@ class _AppTextState extends State { @override void initState() { hidden = widget.readMore; - if (widget.style == "overline") + if (widget.style == "overline") { text = widget.text.toUpperCase(); - else { + } else { text = widget.text; } super.initState(); @@ -133,7 +132,7 @@ class _AppTextState extends State { widget.readMore && text.length > widget.maxLength) Padding( - padding: EdgeInsets.only(top: 8.0, right: 8.0, bottom: 8.0), + padding: const EdgeInsets.only(top: 8.0, right: 8.0, bottom: 8.0), child: InkWell( onTap: () { setState(() { @@ -151,12 +150,6 @@ class _AppTextState extends State { ], ), ), - // onLongPress: (){ - // if(widget.isCopyable){ - // DrAppToastMsg.showShortToast(TranslationBase.of(context).textCopiedSuccessfully); - // Clipboard.setData(new ClipboardData(text: widget.text)); - // } - // }, ); } @@ -164,42 +157,40 @@ class _AppTextState extends State { if (widget.isCopyable) { return Theme( data: ThemeData( - textSelectionColor: Colors.lightBlueAccent, + textSelectionTheme: const TextSelectionThemeData(selectionColor: Colors.lightBlueAccent), ), - child: Container( - child: SelectableText( - !hidden - ? text - : (text.substring( - 0, - text.length > widget.maxLength - ? widget.maxLength - : text.length)), - textAlign: widget.textAlign, - // overflow: widget.maxLines != null - // ? ((widget.maxLines > 1) - // ? TextOverflow.fade - // : TextOverflow.ellipsis) - // : null, - maxLines: widget.maxLines ?? null, - style: widget.style != null - ? _getFontStyle().copyWith( - fontStyle: widget.italic ? FontStyle.italic : null, - color: widget.color, - fontWeight: widget.fontWeight ?? _getFontWeight(), - height: widget.fontHeight) - : TextStyle( - fontStyle: widget.italic ? FontStyle.italic : null, - color: - widget.color != null ? widget.color : Color(0xff2E303A), - fontSize: widget.fontSize ?? _getFontSize(), - letterSpacing: widget.letterSpacing ?? - (widget.variant == "overline" ? 1.5 : null), - fontWeight: widget.fontWeight ?? _getFontWeight(), - fontFamily: widget.fontFamily ?? 'Poppins', - decoration: widget.textDecoration, - height: widget.fontHeight), - ), + child: SelectableText( + !hidden + ? text + : (text.substring( + 0, + text.length > widget.maxLength + ? widget.maxLength + : text.length)), + textAlign: widget.textAlign, + // overflow: widget.maxLines != null + // ? ((widget.maxLines > 1) + // ? TextOverflow.fade + // : TextOverflow.ellipsis) + // : null, + maxLines: widget.maxLines, + style: widget.style != null + ? _getFontStyle().copyWith( + fontStyle: widget.italic ? FontStyle.italic : null, + color: widget.color, + fontWeight: widget.fontWeight ?? _getFontWeight(), + height: widget.fontHeight) + : TextStyle( + fontStyle: widget.italic ? FontStyle.italic : null, + color: + widget.color ?? const Color(0xff000000), + fontSize: widget.fontSize ?? _getFontSize(), + letterSpacing: widget.letterSpacing ?? + (widget.variant == "overline" ? 1.5 : null), + fontWeight: widget.fontWeight ?? _getFontWeight(), + fontFamily: widget.fontFamily ?? 'Poppins', + decoration: widget.textDecoration, + height: widget.fontHeight), ), ); } else { @@ -217,7 +208,7 @@ class _AppTextState extends State { ? TextOverflow.fade : TextOverflow.ellipsis) : null, - maxLines: widget.maxLines ?? null, + maxLines: widget.maxLines, style: widget.style != null ? _getFontStyle().copyWith( fontStyle: widget.italic ? FontStyle.italic : null, @@ -226,7 +217,7 @@ class _AppTextState extends State { height: widget.fontHeight) : TextStyle( fontStyle: widget.italic ? FontStyle.italic : null, - color: widget.color != null ? widget.color : Colors.black, + color: widget.color ?? Colors.black, fontSize: widget.fontSize ?? _getFontSize(), letterSpacing: widget.letterSpacing ?? (widget.variant == "overline" ? 1.5 : null), @@ -263,7 +254,7 @@ class _AppTextState extends State { case "button": return Theme.of(context).textTheme.button; default: - return TextStyle(); + return const TextStyle(); } } @@ -300,7 +291,7 @@ class _AppTextState extends State { case "date": return 24.0; default: - return SizeConfig.textMultiplier * 2; + return SizeConfig.textMultiplier * 2.8; } } diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 9994324..addc988 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,8 +5,16 @@ import FlutterMacOS import Foundation +import audio_session import connectivity_macos +import flutter_tts +import just_audio +import path_provider_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin")) ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) + FlutterTtsPlugin.register(with: registry.registrar(forPlugin: "FlutterTtsPlugin")) + JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) } diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 6ade3d5..6b9af40 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 6AAE3FFB3F8FFB988FA76AB9 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 11DB0DA04C904ACC8281A43B /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -52,9 +53,10 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 11DB0DA04C904ACC8281A43B /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* queuing_system.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "queuing_system.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* queuing_system.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = queuing_system.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -66,8 +68,11 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 48B59F1CA514D4FE4E3BDC17 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + B1FB68A5A367B781DB228777 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + B5F3688D63D2A57A68A0C215 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -75,12 +80,24 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 6AAE3FFB3F8FFB988FA76AB9 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 03070B72BAE9950C266BFD12 /* Pods */ = { + isa = PBXGroup; + children = ( + 48B59F1CA514D4FE4E3BDC17 /* Pods-Runner.debug.xcconfig */, + B1FB68A5A367B781DB228777 /* Pods-Runner.release.xcconfig */, + B5F3688D63D2A57A68A0C215 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; 33BA886A226E78AF003329D5 /* Configs */ = { isa = PBXGroup; children = ( @@ -99,6 +116,7 @@ 33CEB47122A05771004F2AC0 /* Flutter */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, + 03070B72BAE9950C266BFD12 /* Pods */, ); sourceTree = ""; }; @@ -148,6 +166,7 @@ D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( + 11DB0DA04C904ACC8281A43B /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; @@ -159,11 +178,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + AD55B7E3AC663188F5990F5E /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + E17CB185511E52C6C3C36151 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -270,6 +291,45 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; + AD55B7E3AC663188F5990F5E /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + E17CB185511E52C6C3C36151 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..21a3cc1 100644 --- a/macos/Runner.xcworkspace/contents.xcworkspacedata +++ b/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/pubspec.lock b/pubspec.lock index b88033d..35bf3c8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,7 +7,21 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.8.2" + version: "2.9.0" + audio_session: + dependency: transitive + description: + name: audio_session + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.13" + blinking_text: + dependency: "direct main" + description: + name: blinking_text + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" boolean_selector: dependency: transitive description: @@ -21,7 +35,7 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" charcode: dependency: transitive description: @@ -35,14 +49,14 @@ packages: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" + version: "1.16.0" connectivity: dependency: "direct main" description: @@ -91,7 +105,21 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.4" flutter: dependency: "direct main" description: flutter @@ -123,6 +151,13 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_tts: + dependency: "direct main" + description: + name: flutter_tts + url: "https://pub.dartlang.org" + source: hosted + version: "3.6.3" flutter_web_plugins: dependency: transitive description: flutter @@ -155,7 +190,28 @@ packages: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.3" + version: "0.6.4" + just_audio: + dependency: "direct main" + description: + name: just_audio + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.31" + just_audio_platform_interface: + dependency: transitive + description: + name: just_audio_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.0" + just_audio_web: + dependency: transitive + description: + name: just_audio_web + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.7" lints: dependency: transitive description: @@ -176,14 +232,21 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.11" + version: "0.12.12" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.5" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0" nested: dependency: transitive description: @@ -197,7 +260,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.2" path_drawing: dependency: transitive description: @@ -212,6 +275,55 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.0" + path_provider: + dependency: transitive + description: + name: path_provider + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.11" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.20" + path_provider_ios: + dependency: transitive + description: + name: path_provider_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.11" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.7" + path_provider_macos: + dependency: transitive + description: + name: path_provider_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.6" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.3" petitparser: dependency: transitive description: @@ -219,6 +331,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.4.0" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" plugin_platform_interface: dependency: transitive description: @@ -226,6 +345,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.2" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.4" provider: dependency: "direct main" description: @@ -240,6 +366,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.1+1" + rxdart: + dependency: transitive + description: + name: rxdart + url: "https://pub.dartlang.org" + source: hosted + version: "0.27.7" signalr_core: dependency: "direct main" description: @@ -258,7 +391,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.9.0" sse_client: dependency: transitive description: @@ -286,21 +419,21 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.3" + version: "0.4.12" tuple: dependency: transitive description: @@ -315,13 +448,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.0" + uuid: + dependency: transitive + description: + name: uuid + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.6" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.2" web_socket_channel: dependency: transitive description: @@ -329,6 +469,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0+2" xml: dependency: transitive description: @@ -337,5 +491,5 @@ packages: source: hosted version: "5.3.1" sdks: - dart: ">=2.14.0 <3.0.0" - flutter: ">=2.4.0-0.0.pre" + dart: ">=2.17.0 <3.0.0" + flutter: ">=3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index f2656a8..6f0a180 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,6 +38,9 @@ dependencies: flutter_gifimage: ^1.0.1 flutter_svg: ^1.0.3 http: ^0.13.0 + blinking_text: ^1.0.2 + just_audio: ^0.9.31 + flutter_tts: ^3.6.3 #signalr core signalr_core: ^1.1.1 @@ -69,32 +72,24 @@ flutter: uses-material-design: true # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware. - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/custom-fonts/#from-packages + assets: + - assets/images/ + - assets/voice_en/ + - assets/voice_ar/ + + + fonts: + - family: Poppins + fonts: + - asset: assets/fonts/Poppins/Poppins-Regular.ttf + weight: 400 + - asset: assets/fonts/Poppins/Poppins-Medium.ttf + weight: 500 + - asset: assets/fonts/Poppins/Poppins-SemiBold.ttf + weight: 600 + - asset: assets/fonts/Poppins/Poppins-Bold.ttf + weight: 700 + - asset: assets/fonts/Poppins/Poppins-Bold.ttf + weight: 800 + - asset: assets/fonts/Poppins/Poppins-Bold.ttf + weight: 900 diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 8b6d468..63d4407 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,6 +6,9 @@ #include "generated_plugin_registrant.h" +#include void RegisterPlugins(flutter::PluginRegistry* registry) { + FlutterTtsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterTtsPlugin")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 4d10c25..26bfe68 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,10 @@ # list(APPEND FLUTTER_PLUGIN_LIST + flutter_tts +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST ) set(PLUGIN_BUNDLED_LIBRARIES) @@ -13,3 +17,8 @@ foreach(plugin ${FLUTTER_PLUGIN_LIST}) list(APPEND PLUGIN_BUNDLED_LIBRARIES $) list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin)