diff --git a/android/app/build.gradle b/android/app/build.gradle index e55e2b22..4f0659df 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -54,22 +54,25 @@ android { } signingConfigs { - release { - keyAlias keystoreProperties['keyAlias'] - keyPassword keystoreProperties['keyPassword'] - storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null - storePassword keystoreProperties['storePassword'] - } +// release { +// keyAlias keystoreProperties['keyAlias'] +// keyPassword keystoreProperties['keyPassword'] +// storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null +// storePassword keystoreProperties['storePassword'] +// } } buildTypes { debug { signingConfig signingConfigs.debug } release { - minifyEnabled true - shrinkResources true - signingConfig signingConfigs.release + signingConfig signingConfigs.debug } +// release { +// minifyEnabled true +// shrinkResources true +// signingConfig signingConfigs.release +// } } } diff --git a/assets/images/cloud_logo.png b/assets/images/cloud_logo.png new file mode 100644 index 00000000..a1f1aaed Binary files /dev/null and b/assets/images/cloud_logo.png differ diff --git a/assets/images/doc.png b/assets/images/doc.png new file mode 100644 index 00000000..e7418db8 Binary files /dev/null and b/assets/images/doc.png differ diff --git a/assets/images/excel.png b/assets/images/excel.png new file mode 100644 index 00000000..470e1be5 Binary files /dev/null and b/assets/images/excel.png differ diff --git a/assets/images/pdf.png b/assets/images/pdf.png new file mode 100644 index 00000000..3102284f Binary files /dev/null and b/assets/images/pdf.png differ diff --git a/assets/images/sub_workorder_icon.svg b/assets/images/sub_workorder_icon.svg new file mode 100644 index 00000000..4400caae --- /dev/null +++ b/assets/images/sub_workorder_icon.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/subtitles/ar_subtitle.json b/assets/subtitles/ar_subtitle.json index ada5f900..e419c327 100644 --- a/assets/subtitles/ar_subtitle.json +++ b/assets/subtitles/ar_subtitle.json @@ -3,8 +3,6 @@ "failed_request_message": "الفشل في إكمال الطلب", "successful_request_message": "تم إكمال الطلب بنجاح", "request_lock_message": "انتظر حتى إكمال الطلب", - - "cancel": "إلغاء", "confirm": "تاكيد", "done": "تم", @@ -13,7 +11,6 @@ "sign_out": "تسجيل الخروج", "logout_alert": "هل انت متاكد من رغبتك في تسجيل الخروج؟", "language": "اللغة", - "name": "الاسم", "email": "البريد الالكتروني", "phone_number": "رقم الهاتف", @@ -29,7 +26,6 @@ "confirm_password_validate_message": "كلمة المرور و تاكيد كلمة المرور غير متطابقان", "phone_number_validate_message": "رقم الهاتف غير صالح", "terms_and_conditions_validate_message": "موافقة علي الشروط والاحكام مطاوبة", - "update": "تحديث", "step": "خطوة", "forget_password_with_mark": "نسيت كلمة المرور؟", @@ -59,7 +55,6 @@ "title_not_found": "لا يوجد عنوان", "title_validate_message": "العنوان مطلوب", "url_not_found": "لا يوجد رابط", - "date": "تاريخ", "status": "الحالة", "code": "كود", @@ -74,10 +69,9 @@ "details": "تفاصيل", "device": "جهاز", "deviceArName": "اسم الجهاز بعربي", - "deviceEnName": "اسم الجهاز بالانجليزية", + "deviceName": "اسم الجهاز", "deviceImages": "صور الجهاز", "deviceModel": "مركة الجهاز", - "deviceName": "اسم الجهاز", "deviceRequired": "الجهاز مطلوب", "deviceSN": "رقم تسلسلي للجهاز", "engineerName": "اسم المهندس", @@ -135,9 +129,7 @@ "visitDate": "تاريخ الزيارة", "whatsApp": "واتساب", "workPerformed": "العمل انجز", - "actualDate": "تاريخ الفعلي", - "done": "تم الانتهاء", "expectDate": "التاريخ المتوقع", "images": "الصور", "imagesRequired": "الصور مطلوبة", @@ -166,7 +158,6 @@ "requiredImage": "الصورة مطلوبة", "taskStatus": "حالة الطلب", "activationAlert": "الحساب قيد المراجعة يرجى الانتظار حتى يتم تفعيله", - "attachImage": "ارفق صورة", "callLastSituation": "اخر موقف للطلب", "customer": "العميل", @@ -176,17 +167,40 @@ "newServiceReport": "تقرير خدمة جديد", "number": "رقم", "operatingHours": "ساعات العمل", - "partNumber": "رقم القطعة", + "partNumberName": "رقم/اسم القطعة", "quantity": "كمية", "reasons": "الاسباب", "reportStatus": "حالة التقرير", "reportType": "نوع التقرير", "callId": "رقم الطلب", "requiredWord": "مطلوب", - "serviceType": "نوع الخدمة", + "AssetType": "نوع الاصل", "workPreformed": "العمل المنجز", "alert": "تنبيه", "duplicateAlert": "تنبيه التكرار", "duplicateAlertMessage": "هل أنت متأكد أنك تريد تكرار الطلب؟", - "duplicateRequest": "تكرار الطلب" + "duplicateRequest": "تكرار الطلب", + "orderWorkNumber": "رقم طلب العمل", + "assignedEmployee": "الموظف المعين", + "assetSN": "رقم تسلسلي للاصل ", + "assetName": "اسم الاصل", + "assetNumber": "رقم الاصل", + "site": "الموقع", + "maintenanceSituation": "موقع الصيانه", + "currentSituation": "الموقع الحالي", + "comment": "تعليق", + "updateServiceRequest": "تعديل طلب الخدمة", + "repairLocation": "موقع الإصلاح", + "travelingExpense": "مصاريف التنقل", + "startDate": "وقت البدء", + "requestedQuantity": "الكمية المطلوبة", + "deliveredQuantity": "الكمية المسلّمة", + "endDate": "وقت الانتهاء", + "destinationSite": "موقع الوجهه", + "building": "بناء", + "floor": "طابق", + "department": "قسم", + "room": "غرفه", + "actions": "اجراءات", + "deviceFiles": "ملفات الجهاز" } \ No newline at end of file diff --git a/assets/subtitles/en_subtitle.json b/assets/subtitles/en_subtitle.json index 2ce29fb9..33ff94b5 100644 --- a/assets/subtitles/en_subtitle.json +++ b/assets/subtitles/en_subtitle.json @@ -3,7 +3,6 @@ "failed_request_message": "Failed to complete request", "successful_request_message": "Request complete successfully", "request_lock_message": "Wait until your request complete", - "cancel": "Cancel", "confirm": "Confirm", "done": "Done", @@ -12,7 +11,6 @@ "sign_out": "Sign Out", "logout_alert": "Are you sure you want to Sign Out?", "language": "English", - "name": "Name", "email": "Email", "phone_number": "Phone Number", @@ -28,7 +26,6 @@ "confirm_password_validate_message": "Password and confirm password not match", "phone_number_validate_message": "Not valid phone number", "terms_and_conditions_validate_message": "Accept terms and conditions is required", - "update": "Update", "step": "Step", "forget_password_with_mark": "Forget Password?", @@ -58,7 +55,6 @@ "title_not_found": "Title not found", "title_validate_message": "Title Can't be empty", "url_not_found": "URL not found", - "date": "Date", "status": "Status", "code": "Code", @@ -73,12 +69,11 @@ "details": "Details", "device": "Asset", "deviceArName": "Asset Ar Name", - "deviceEnName": "Asset En Name", + "deviceName": "Asset Name", "deviceImages": "Asset Images", "deviceModel": "Asset Model", - "deviceName": "Asset Name", "deviceRequired": "Asset Required", - "deviceSN": "Asset SN", + "deviceSN": "Asset Serial Number", "engineerName": "Engineer Name", "engineerPhone": "Engineer Phone", "facebook": "facebook", @@ -134,9 +129,7 @@ "visitDate": "Visit Date", "whatsApp": "WhatsApp", "workPerformed": "Work Performed", - "actualDate": "Actual Date", - "done": "Done", "expectDate": "Expect Date", "images": "Images", "imagesRequired": "Images Required", @@ -165,7 +158,6 @@ "requiredImage": "Image Required", "taskStatus": "Task Status", "activationAlert": "Account under reviewing please wait until be activated", - "attachImage": "Attach Image", "callLastSituation": "Call's Last Situation", "customer": "Customer", @@ -175,18 +167,40 @@ "newServiceReport": "New Work Order", "number": "Number", "operatingHours": "Operating Hours", - "partNumber": "Part Number", + "partNumberName": "Part Number/Name", "quantity": "Quantity", "reasons": "Reasons", "reportStatus": "Report Status", "reportType": "Report Type", "callId": "Call Id", "requiredWord": "required", - "serviceType": "Service Type", + "AssetType": "Asset Type", "workPreformed": "Work Preformed", - + "orderWorkNumber": "Order Work Number", + "assignedEmployee": "Assigned Employee", + "assetSN": "Asset S.N", + "assetName": "Asset Name", + "assetNumber": "Asset Number", + "site": "Site", + "maintenanceSituation": "Maintenance Situation", + "currentSituation": "Current Situation", "alert": "Alert", "duplicateAlert": "Duplicate Alert", "duplicateAlertMessage": "Are you sure you want to duplicate request?", - "duplicateRequest": "Duplicate Request" + "duplicateRequest": "Duplicate Request", + "comment": "Comment", + "updateServiceRequest": "Update Service Request", + "repairLocation": "Repair Location", + "travelingExpense": "Traveling Expense", + "startDate": "Start Date", + "requestedQuantity": "Requested Quantity", + "deliveredQuantity": "Delivered Quantity", + "endDate": "End Date", + "destinationSite": "Destination Site", + "building": "Building", + "floor": "Floor", + "department": "Department", + "room": "Room", + "actions": "Actions", + "deviceFiles": "Asset Files" } \ No newline at end of file diff --git a/ios/Podfile b/ios/Podfile index 2c068c40..2dff4172 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -38,4 +38,16 @@ post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) end + installer.generated_projects.each do |project| + project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0' + config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ + '$(inherited)', + ## dart: PermissionGroup.microphone + 'PERMISSION_MICROPHONE=1', + ] + end + end + end end diff --git a/ios/Podfile.lock b/ios/Podfile.lock deleted file mode 100644 index cbf76fea..00000000 --- a/ios/Podfile.lock +++ /dev/null @@ -1,216 +0,0 @@ -PODS: - - audioplayers_darwin (0.0.1): - - Flutter - - Firebase/CoreOnly (10.3.0): - - FirebaseCore (= 10.3.0) - - Firebase/Messaging (10.3.0): - - Firebase/CoreOnly - - FirebaseMessaging (~> 10.3.0) - - firebase_core (2.4.1): - - Firebase/CoreOnly (= 10.3.0) - - Flutter - - firebase_messaging (14.2.1): - - Firebase/Messaging (= 10.3.0) - - firebase_core - - Flutter - - FirebaseCore (10.3.0): - - FirebaseCoreInternal (~> 10.0) - - GoogleUtilities/Environment (~> 7.8) - - GoogleUtilities/Logger (~> 7.8) - - FirebaseCoreInternal (10.3.0): - - "GoogleUtilities/NSData+zlib (~> 7.8)" - - FirebaseInstallations (10.3.0): - - FirebaseCore (~> 10.0) - - GoogleUtilities/Environment (~> 7.8) - - GoogleUtilities/UserDefaults (~> 7.8) - - PromisesObjC (~> 2.1) - - FirebaseMessaging (10.3.0): - - FirebaseCore (~> 10.0) - - FirebaseInstallations (~> 10.0) - - GoogleDataTransport (~> 9.2) - - GoogleUtilities/AppDelegateSwizzler (~> 7.8) - - GoogleUtilities/Environment (~> 7.8) - - GoogleUtilities/Reachability (~> 7.8) - - GoogleUtilities/UserDefaults (~> 7.8) - - nanopb (< 2.30910.0, >= 2.30908.0) - - Flutter (1.0.0) - - flutter_keyboard_visibility (0.0.1): - - Flutter - - flutter_local_notifications (0.0.1): - - Flutter - - flutter_sound (9.2.13): - - Flutter - - flutter_sound_core (= 9.2.13) - - flutter_sound_core (9.2.13) - - fluttertoast (0.0.2): - - Flutter - - Toast - - FMDB (2.7.5): - - FMDB/standard (= 2.7.5) - - FMDB/standard (2.7.5) - - GoogleDataTransport (9.2.0): - - GoogleUtilities/Environment (~> 7.7) - - nanopb (< 2.30910.0, >= 2.30908.0) - - PromisesObjC (< 3.0, >= 1.2) - - GoogleUtilities/AppDelegateSwizzler (7.10.0): - - GoogleUtilities/Environment - - GoogleUtilities/Logger - - GoogleUtilities/Network - - GoogleUtilities/Environment (7.10.0): - - PromisesObjC (< 3.0, >= 1.2) - - GoogleUtilities/Logger (7.10.0): - - GoogleUtilities/Environment - - GoogleUtilities/Network (7.10.0): - - GoogleUtilities/Logger - - "GoogleUtilities/NSData+zlib" - - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (7.10.0)" - - GoogleUtilities/Reachability (7.10.0): - - GoogleUtilities/Logger - - GoogleUtilities/UserDefaults (7.10.0): - - GoogleUtilities/Logger - - image_picker_ios (0.0.1): - - Flutter - - MTBBarcodeScanner (5.0.11) - - nanopb (2.30909.0): - - nanopb/decode (= 2.30909.0) - - nanopb/encode (= 2.30909.0) - - nanopb/decode (2.30909.0) - - nanopb/encode (2.30909.0) - - package_info (0.0.1): - - Flutter - - path_provider_ios (0.0.1): - - Flutter - - permission_handler_apple (9.0.4): - - Flutter - - PromisesObjC (2.1.1) - - qr_code_scanner (0.2.0): - - Flutter - - MTBBarcodeScanner - - share (0.0.1): - - Flutter - - shared_preferences_ios (0.0.1): - - Flutter - - speech_to_text (0.0.1): - - Flutter - - Try - - sqflite (0.0.2): - - Flutter - - FMDB (>= 2.7.5) - - Toast (4.0.0) - - Try (2.1.1) - - url_launcher_ios (0.0.1): - - Flutter - -DEPENDENCIES: - - audioplayers_darwin (from `.symlinks/plugins/audioplayers_darwin/ios`) - - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) - - Flutter (from `Flutter`) - - flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`) - - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) - - flutter_sound (from `.symlinks/plugins/flutter_sound/ios`) - - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - - package_info (from `.symlinks/plugins/package_info/ios`) - - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`) - - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - - qr_code_scanner (from `.symlinks/plugins/qr_code_scanner/ios`) - - share (from `.symlinks/plugins/share/ios`) - - shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`) - - speech_to_text (from `.symlinks/plugins/speech_to_text/ios`) - - sqflite (from `.symlinks/plugins/sqflite/ios`) - - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - -SPEC REPOS: - trunk: - - Firebase - - FirebaseCore - - FirebaseCoreInternal - - FirebaseInstallations - - FirebaseMessaging - - flutter_sound_core - - FMDB - - GoogleDataTransport - - GoogleUtilities - - MTBBarcodeScanner - - nanopb - - PromisesObjC - - Toast - - Try - -EXTERNAL SOURCES: - audioplayers_darwin: - :path: ".symlinks/plugins/audioplayers_darwin/ios" - firebase_core: - :path: ".symlinks/plugins/firebase_core/ios" - firebase_messaging: - :path: ".symlinks/plugins/firebase_messaging/ios" - Flutter: - :path: Flutter - flutter_keyboard_visibility: - :path: ".symlinks/plugins/flutter_keyboard_visibility/ios" - flutter_local_notifications: - :path: ".symlinks/plugins/flutter_local_notifications/ios" - flutter_sound: - :path: ".symlinks/plugins/flutter_sound/ios" - fluttertoast: - :path: ".symlinks/plugins/fluttertoast/ios" - image_picker_ios: - :path: ".symlinks/plugins/image_picker_ios/ios" - package_info: - :path: ".symlinks/plugins/package_info/ios" - path_provider_ios: - :path: ".symlinks/plugins/path_provider_ios/ios" - permission_handler_apple: - :path: ".symlinks/plugins/permission_handler_apple/ios" - qr_code_scanner: - :path: ".symlinks/plugins/qr_code_scanner/ios" - share: - :path: ".symlinks/plugins/share/ios" - shared_preferences_ios: - :path: ".symlinks/plugins/shared_preferences_ios/ios" - speech_to_text: - :path: ".symlinks/plugins/speech_to_text/ios" - sqflite: - :path: ".symlinks/plugins/sqflite/ios" - url_launcher_ios: - :path: ".symlinks/plugins/url_launcher_ios/ios" - -SPEC CHECKSUMS: - audioplayers_darwin: 877d9a4d06331c5c374595e46e16453ac7eafa40 - Firebase: f92fc551ead69c94168d36c2b26188263860acd9 - firebase_core: bf59c32d2e53814f558efa20840c1902fa2fe461 - firebase_messaging: ee597229fc260f8fa491fa8f2d4a32dfbfa406fa - FirebaseCore: 988754646ab3bd4bdcb740f1bfe26b9f6c0d5f2a - FirebaseCoreInternal: 29b76f784d607df8b2a1259d73c3f04f1210137b - FirebaseInstallations: e2f26126089dcf41e215f7b8925af8d953c7d602 - FirebaseMessaging: e345b219fd15d325f0cf2fef28cb8ce00d851b3f - Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 - flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069 - flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743 - flutter_sound: c60effa2a350fb977885f0db2fbc4c1ad5160900 - flutter_sound_core: 26c10e5832e76aaacfae252d8925232281c486ae - fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0 - FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a - GoogleDataTransport: 1c8145da7117bd68bbbed00cf304edb6a24de00f - GoogleUtilities: bad72cb363809015b1f7f19beb1f1cd23c589f95 - image_picker_ios: b786a5dcf033a8336a657191401bfdf12017dabb - MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb - nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431 - package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 - path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02 - permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce - PromisesObjC: ab77feca74fa2823e7af4249b8326368e61014cb - qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e - share: 0b2c3e82132f5888bccca3351c504d0003b3b410 - shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad - speech_to_text: b43a7d99aef037bd758ed8e45d79bbac035d2dfe - sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 - Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 - Try: 5ef669ae832617b3cee58cb2c6f99fb767a4ff96 - url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de - -PODFILE CHECKSUM: 4e8f8b2be68aeea4c0d5beb6ff1e79fface1d048 - -COCOAPODS: 1.11.3 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index a5559bc2..471a4caa 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -160,6 +160,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { + BuildIndependentTargetsInParallel = YES; LastUpgradeCheck = 1300; ORGANIZATIONNAME = ""; TargetAttributes = { @@ -227,6 +228,7 @@ }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -258,6 +260,7 @@ }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -308,6 +311,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -361,6 +365,7 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; @@ -439,16 +444,12 @@ "-framework", "\"package_info\"", "-framework", - "\"path_provider_ios\"", - "-framework", "\"permission_handler_apple\"", "-framework", "\"qr_code_scanner\"", "-framework", "\"share\"", "-framework", - "\"shared_preferences_ios\"", - "-framework", "\"speech_to_text\"", "-framework", "\"sqflite\"", @@ -470,6 +471,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -527,6 +529,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -582,6 +585,7 @@ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; @@ -660,16 +664,12 @@ "-framework", "\"package_info\"", "-framework", - "\"path_provider_ios\"", - "-framework", "\"permission_handler_apple\"", "-framework", "\"qr_code_scanner\"", "-framework", "\"share\"", "-framework", - "\"shared_preferences_ios\"", - "-framework", "\"speech_to_text\"", "-framework", "\"sqflite\"", @@ -693,6 +693,7 @@ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; @@ -771,16 +772,12 @@ "-framework", "\"package_info\"", "-framework", - "\"path_provider_ios\"", - "-framework", "\"permission_handler_apple\"", "-framework", "\"qr_code_scanner\"", "-framework", "\"share\"", "-framework", - "\"shared_preferences_ios\"", - "-framework", "\"speech_to_text\"", "-framework", "\"sqflite\"", diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 339d7ae2..4d661d08 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -7,7 +7,7 @@ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName - Atoms + Atoms SA CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -15,7 +15,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleName - Atoms + Atoms SA CFBundlePackageType APPL CFBundleShortVersionString @@ -36,8 +36,10 @@ This app requires permission to access photo gallery to allow user to attach images NSSpeechRecognitionUsageDescription This app requires permission for Speech Recognition for speech to text functionality. - UIApplicationSupportsIndirectInputEvents - + LSSupportsOpeningDocumentsInPlace + + UISupportsDocumentBrowser + UIBackgroundModes fetch @@ -62,5 +64,7 @@ UIViewControllerBasedStatusBarAppearance + UIApplicationSupportsIndirectInputEvents + diff --git a/lib/controllers/api_routes/api_manager.dart b/lib/controllers/api_routes/api_manager.dart new file mode 100644 index 00000000..77adc8b5 --- /dev/null +++ b/lib/controllers/api_routes/api_manager.dart @@ -0,0 +1,149 @@ +import 'dart:convert'; + +import 'package:flutter/foundation.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:http/http.dart' as http; +import 'package:http/http.dart'; +import 'package:test_sa/models/user.dart'; + +class ApiManager { + ApiManager._(); + + Map get _headers => { + 'Content-Type': 'application/json', + if (user != null) 'Authorization': 'Bearer ${user.token}', + }; + + static ApiManager instance = ApiManager._(); + + User user; + + Future get( + String url, { + Map headers, + enableToastMessage = true, + }) async { + headers ??= {}; + + headers.addAll(_headers); + + Uri _url = Uri.parse(url); + // print(_url); + // print(headers); + http.Response response = await http.get(_url, headers: headers); + if (jsonDecode(response.body) is Map) { + final message = jsonDecode(response.body)["message"]; + if (message != null && message.toString().isNotEmpty && enableToastMessage) { + Fluttertoast.showToast(msg: message ?? "", toastLength: Toast.LENGTH_LONG); + } + } + + return response; + } + + Future post( + String url, { + Map headers, + @required Map body, + }) async { + headers ??= {}; + + headers.addAll(_headers); + + Uri _url = Uri.parse(url); + if (!kReleaseMode) { + print("URL:$_url"); + print("Headers:$headers"); + print("Body:$body"); + } + + var request = http.Request('POST', _url); + request.body = json.encode(body); + request.headers.addAll(headers); + + http.StreamedResponse _streamedResponse = await request.send(); + http.Response response = await http.Response.fromStream(_streamedResponse); +// print(response.statusCode); +// log(response.body); + + if (jsonDecode(response.body) is Map) { + final message = jsonDecode(response.body)["message"]; + if (message != null && message.toString().isNotEmpty) { + Fluttertoast.showToast(msg: message ?? "", toastLength: Toast.LENGTH_LONG); + } + } + + return response; + } + + Future put( + String url, { + Map headers, + @required Map body, + }) async { + headers ??= {}; + + headers.addAll(_headers); + + Uri _url = Uri.parse(url); + print(_url); + // print(headers); + // log(json.encode(body)); + var request = http.Request('PUT', _url); + request.body = json.encode(body); + request.headers.addAll(headers); + + http.StreamedResponse streamedResponse = await request.send(); + http.Response response = await http.Response.fromStream(streamedResponse); + // print(response.statusCode); + // log(response.body); + if (jsonDecode(response.body) is Map) { + final message = jsonDecode(response.body)["message"]; + if (message != null && message.toString().isNotEmpty) { + Fluttertoast.showToast(msg: message ?? "", toastLength: Toast.LENGTH_LONG); + } + } + return response; + } + + Future multiPart( + String url, { + Map headers, + @required Map body, + @required List> files, + }) async { + Map _headers = const { + 'Content-Type': 'multipart/form-data', + }; + + headers ??= {}; + + headers.addAll(_headers); + + Uri _url = Uri.parse(url); + // print(_url); + // print(_headers); + // print(json.encode(body)); + var request = http.MultipartRequest('POST', _url); + request.fields.addAll(body); + request.headers.addAll(_headers); + + for (var element in files) { + request.files.add(await element); + } + + //request.files.addAll(_files); + // print(request.files); + http.StreamedResponse streamedResponse = await request.send(); + http.Response response = await http.Response.fromStream(streamedResponse); + // print(response.statusCode); + // log(response.body); + if (jsonDecode(response.body) is Map) { + final message = jsonDecode(response.body)["message"]; + if (message != null && message.toString().isNotEmpty) { + Fluttertoast.showToast(msg: message ?? "", toastLength: Toast.LENGTH_LONG); + } + } + return response; + } +} diff --git a/lib/controllers/http_status_manger/http_status_manger.dart b/lib/controllers/api_routes/http_status_manger.dart similarity index 79% rename from lib/controllers/http_status_manger/http_status_manger.dart rename to lib/controllers/api_routes/http_status_manger.dart index 012a9a23..f9405f62 100644 --- a/lib/controllers/http_status_manger/http_status_manger.dart +++ b/lib/controllers/api_routes/http_status_manger.dart @@ -1,40 +1,39 @@ -import 'package:test_sa/models/subtitle.dart'; import 'package:meta/meta.dart'; +import 'package:test_sa/models/subtitle.dart'; -class HttpStatusManger{ +class HttpStatusManger { static String getStatusMessage({ @required int status, @required Subtitle subtitle, String messageFor400, String messageFor200, - }){ - if(status == null) + }) { + if (status == null) // no status code - code error no need for subtitle return "careful null status"; - if(status == -1) + if (status == -1) // client's request in process return subtitle.currentlyServiceNotAvailable; - if(status == -2){ + if (status == -2) { // client's request in process return subtitle.waitUntilYourRequestComplete; - }else if(status >= 200 && status < 300){ + } else if (status >= 200 && status < 300) { // client's request was successfully received return messageFor200 ?? subtitle.requestCompleteSuccessfully; - } else if(status >= 400 && status < 500){ + } else if (status >= 400 && status < 500) { // client's request have error - switch(status){ + switch (status) { case 400: return messageFor400 ?? subtitle.failedToCompleteRequest; default: return subtitle.failedToCompleteRequest; } - } else if(status >= 500){ + } else if (status >= 500) { // server error return subtitle.currentlyServiceNotAvailable; } else { // no error match so return default error return subtitle.failedToCompleteRequest; } - } -} \ No newline at end of file +} diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index f2e26591..a587fb7f 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -1,67 +1,105 @@ -class URLs{ +class URLs { URLs._(); + static const host2 = "http://194.163.164.213/atoms/api"; - static const host1 = "https://atoms.hmg.com/api"; + static const host1 = "https://atomsuat.hmg.com"; // uat url + + // static const host1 = "http://109.123.243.118:9000"; + + static String _baseUrl = "$_host/mobile"; + + static String _host = host1; + + set host(String value) => _host = value; + + static String getFileUrl(String file) => (file == null || file.isEmpty) ? null : (file.contains("/") ? file : "$_host/Files/DownloadFile?fileName=$file"); + // static String getFileUrl(String file) => (file == null || file.isEmpty) ? null : (file.contains("/") ? file : "$_host/attachment/$file"); // API Routes - static const login = "/handle/user/login"; // post - static const register = "/handle/create/user"; // post - static const updateProfile = "/update/user/profile"; // post - static const getHospitals = "/handle/return/all/clients"; // get - static const getDepartments = "/handle/return/all/departments"; // get - static const getEquipment = "/handle/return/all/client/equipments"; // get ?client=208051 - static const getServiceRequests = "/return/user/calls"; // get - - static const getPreventiveMaintenanceVisits = "/return/user/calibrations"; // get - static const updatePreventiveMaintenanceVisits = "/update/user/calibrations"; // get - - static const getRegularVisits = "/return/user/ppm"; // get - static const updateRegularVisits = "/update/user/ppm"; // get - - static const getSingleServiceRequest = "/return/call/information"; // get - static const getNotifications = "/return/user/notification"; // get - static const getRecentNotifications = "/return/user/recent/notification"; // get - static const createRequest = "/handle/create/request"; // get - static const createReport = "/handle/create/report/issue"; // get - static const updateRequestDate = "/handle/update/request"; // get + static get login => "$_baseUrl/MobileAuth/LoginIntegration"; // post + static get register => "$_baseUrl/handle/create/user"; // post + static get updateProfile => "$_baseUrl/update/user/profile"; // post + static get getHospitals => "$_baseUrl/Customer/GetCustomers"; // get + static get getHospitalsAutoComplete => "$_baseUrl/Customer/GetCustomersAutoComplete"; // get + + static get getDepartments => "$_baseUrl/Customer/GetDepartmentLookup"; // get + static get getEquipment => "$_baseUrl/Asset/GetAssets"; // get ?client=208051 + static get getModels => "$_baseUrl/ModelDefinition/GetModelDefinitionAsset"; // get ?client=2 + // 08051 + static get getServiceRequests => "$_baseUrl/CallRequest/GetCallRequests"; // get + static get getServiceRequestById => "$_baseUrl/CallRequest/GetCallRequestById"; // get + static get getServiceRequestThrough => "$_baseUrl/Lookups/GetLookup?lookupEnum=603"; // get + static get getServiceLoanAvailability => "$_baseUrl/Lookups/GetLookup?lookupEnum=4"; // get + static get getServiceFirstAction => "$_baseUrl/Lookups/GetLookup?lookupEnum=700"; // get + static get getServiceRequestTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=604"; // get + static get getServiceRequestStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=503"; + + static get getRepairLocation => "$_baseUrl/Lookups/GetLookup?lookupEnum=504"; + + static get equipmentStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=601"; + + static get getDateOperators => "$_baseUrl/Lookups/GetLookup?lookupEnum=200"; + + static get getMaintenanceSituation => "$_baseUrl/Lookups/GetLookup?lookupEnum=502"; + + static get getAllUsers => "http://109.123.243.118:5000/api/Account/GetAllUsers"; + + static get getPreventiveMaintenanceVisits => "$_baseUrl/return/user/calibrations"; // get + static get updatePreventiveMaintenanceVisits => "$_baseUrl/Visit/UpdateVisits"; // get + + static get getRegularVisits => "$_baseUrl/Visit/GetVisits"; // get + static get updateRegularVisits => "$_baseUrl/Visit/UpdateVisits"; // get + + static get getSingleServiceRequest => "$_baseUrl/return/call/information"; // get + static get getNotifications => "$_baseUrl/return/user/notification"; // get + static get getRecentNotifications => "$_baseUrl/return/user/recent/notification"; // get + static get createRequest => "$_baseUrl/CallRequest/AddCallRequest"; // get + static get createReport => "$_baseUrl/handle/create/report/issue"; // get + static get updateRequestDate => "$_baseUrl/CallRequest/UpdateCallRequest"; // get // service report - static const createServiceReport = "/handle/create/service/report"; // get - static const updateServiceReport = "/handle/update/service/report"; // get - static const getServiceReport = "/handle/view/service/report"; // get - static const createDuplicatedReport = "/handle/duplicate/request"; // get - - static const getServiceReportReasons = "/return/service/report/reasons"; // get - static const getServiceReportTypes = "/return/service/report/type"; // get - static const getServiceReportStatus = "/return/service/report/status"; // get - static const getServiceReportLastCalls = "/return/call/last/situation"; // get - static const getServiceTypes = "/return/service/type"; // get - static const getPartNumber = "/handle/return/all/parts"; // get - static const getServiceReportPriority = "/return/call/priority/list"; // get - static const getServiceReportDefectTypes = "/return/call/defect/type/list"; // get + static get createServiceReport => "$_baseUrl/WorkOrder/AddWorkOrder"; // get + static get updateServiceReport => "$_baseUrl/WorkOrder/UpdateWorkOrder"; // get + static get getServiceReport => "$_baseUrl/WorkOrder/GetWorkOrderById"; // get + static get createDuplicatedReport => "$_baseUrl/handle/duplicate/request"; // get + static get searchWorkOrders => "$_baseUrl/WorkOrder/SearchWorkOrders"; + + static get getServiceReportReasons => "$_baseUrl/Lookups/GetLookup?lookupEnum=522"; // get + static get getServiceReportTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=501"; // get + static get getServiceReportStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=521"; // get + static get getServiceReportLastCalls => "$_baseUrl/WorkOrder/GetLookupCallLastSituationBasedOnCase"; // get + static get getAssetTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=500"; // get + static get getPartNumber => "$_baseUrl/PartCatalog/GetPartAutoComplete"; // get + static get getServiceReportPriority => "$_baseUrl/Lookups/GetLookup?lookupEnum=602"; // get + static get getServiceReportDefectTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=601"; // get + static get getCallRequestForWorkOrder => "$_baseUrl/CallRequest/GetCallRequestForWorkOrder"; // get //gas refill - static const getGasTypes = "/return/gas/refill/types"; // get - static const getGasCylinderSize = "/return/gas/refill/size/cylinder"; // get - static const getGasStatus = "/return/gas/refill/status"; // get - static const requestGasRefill = "/create/gas/refill"; // get - static const updateGasRefill = "/update/gas/refill/"; // get - static const getGasRefill = "/search/gas/refill"; // get + static get getGasTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=606"; // get + // todo check edits with backend + static get getGasCylinderSize => "$_baseUrl/Lookups/GetLookup?lookupEnum=608"; // get + static get getGasCylinderType => "$_baseUrl/Lookups/GetLookup?lookupEnum=607"; // get + static get getGasStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=609"; // get + static get requestGasRefill => "$_baseUrl/GazRefill/AddGazRefill"; // get + static get updateGasRefill => "$_baseUrl/GazRefill/UpdateGazRefill"; // get + static get getGasRefill => "$_baseUrl/GazRefill/GetGazRefills"; // get //device transfer - static const requestDeviceTransfer = "/create/transfer/asset"; // get - static const updateDeviceTransfer = "/update/transfer/asset"; // get - static const getDeviceTransfer = "/search/transfer/asset"; // get + static get requestDeviceTransfer => "$_baseUrl/AssetTransfer/AddAssetTransfer"; // get + static get updateDeviceTransfer => "$_baseUrl/AssetTransfer/UpdateAssetTransfer"; // get + static get getDeviceTransfer => "$_baseUrl/AssetTransfer/GetAssetTransfers"; // get + static get getAssetTransferById => "$_baseUrl/AssetTransfer/GetAssetTransferById"; // get // employee - static const getEmployees = "/return/assigned/employee"; // get + static get getEmployees => "$_baseUrl/Lookups/GetLookup?lookupEnum=33"; // get + static get getEngineers => "$_baseUrl/Account/GetUserByRoleValue?value=R-6"; // get + // pentry - static const getPentry = "/return/pentry/details"; // get - static const updatePentry = "/update/pentry/details"; // get - static const getPentryTaskStatus = "/return/pentry/task/status"; // get - static const getPentryVisitStatus = "/return/pentry/visit/status/list"; // get - static const getPentryStatus = "/return/pentry/status/list"; // get + static get getPentry => "$_baseUrl/return/pentry/details"; // get + static get updatePentry => "$_baseUrl/Visit/UpdateVisit"; // get + static get getPentryTaskStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=403"; // get + static get getPentryVisitStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=402"; // get + static get getPentryStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=401"; // get // contacts - static const getPentryContacts = "/handle/return/all/contacts"; // get - -} \ No newline at end of file + static get getPentryContacts => "$_baseUrl/handle/return/all/contacts"; // get +} diff --git a/lib/controllers/localization/localization.dart b/lib/controllers/localization/localization.dart index a6e7fe82..182833e2 100644 --- a/lib/controllers/localization/localization.dart +++ b/lib/controllers/localization/localization.dart @@ -4,7 +4,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:test_sa/models/subtitle.dart'; - class AppLocalization { AppLocalization(this.locale); @@ -17,23 +16,20 @@ class AppLocalization { Subtitle get subtitle => _subtitle; Future load() async { - String jsonStringValues = - await rootBundle.loadString('assets/subtitles/${locale.languageCode}_subtitle.json'); + String jsonStringValues = await rootBundle.loadString('assets/subtitles/${locale.languageCode}_subtitle.json'); _subtitle = Subtitle.fromJson(json.decode(jsonStringValues)); } // static member to have simple access to the delegate from Material App - static const LocalizationsDelegate delegate = - _DemoLocalizationsDelegate(); + static const LocalizationsDelegate delegate = _DemoLocalizationsDelegate(); } -class _DemoLocalizationsDelegate - extends LocalizationsDelegate { +class _DemoLocalizationsDelegate extends LocalizationsDelegate { const _DemoLocalizationsDelegate(); @override bool isSupported(Locale locale) { - return ['en','ar'].contains(locale.languageCode); + return ['en', 'ar'].contains(locale.languageCode); } @override @@ -45,4 +41,4 @@ class _DemoLocalizationsDelegate @override bool shouldReload(LocalizationsDelegate old) => false; -} \ No newline at end of file +} diff --git a/lib/controllers/notification/firebase_notification_manger.dart b/lib/controllers/notification/firebase_notification_manger.dart index 153d28fa..7e92b918 100644 --- a/lib/controllers/notification/firebase_notification_manger.dart +++ b/lib/controllers/notification/firebase_notification_manger.dart @@ -7,8 +7,7 @@ import 'package:test_sa/models/app_notification.dart'; import 'notification_manger.dart'; -class FirebaseNotificationManger{ - +class FirebaseNotificationManger { static FirebaseMessaging messaging = FirebaseMessaging.instance; static String token; @@ -23,7 +22,7 @@ class FirebaseNotificationManger{ sound: true, ); - if(settings.authorizationStatus == AuthorizationStatus.authorized){ + if (settings.authorizationStatus == AuthorizationStatus.authorized) { token = await messaging.getToken(); } return token; @@ -32,7 +31,7 @@ class FirebaseNotificationManger{ static initialized(BuildContext context) async { await Firebase.initializeApp(); NotificationSettings settings; - try{ + try { settings = await messaging.requestPermission( alert: true, announcement: false, @@ -42,11 +41,11 @@ class FirebaseNotificationManger{ provisional: false, sound: true, ); - }catch(error){ + } catch (error) { return; } - if(settings.authorizationStatus != AuthorizationStatus.authorized){ + if (settings.authorizationStatus != AuthorizationStatus.authorized) { return; } @@ -56,28 +55,17 @@ class FirebaseNotificationManger{ FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { AppNotification notification = AppNotification.fromJson(message.data); - if(notification.path == null - || notification.path.isEmpty) - return; - Navigator.pushNamed( - context, - notification.path, - arguments: notification.requestId - ); + if (notification.path == null || notification.path.isEmpty) return; + Navigator.pushNamed(context, notification.path, arguments: notification.requestId); }); FirebaseMessaging.onMessage.listen((RemoteMessage message) { AppNotification notification = AppNotification.fromJson(message.data); NotificationManger.showNotification( - title: message.notification.title, - subtext: message.notification.body, - hashcode: int.tryParse(notification.requestId ?? "") ?? 1, - payload: json.encode(message.data) - ); + title: message.notification.title, subtext: message.notification.body, hashcode: int.tryParse(notification.requestId ?? "") ?? 1, payload: json.encode(message.data)); return; }); } } -Future firebaseMessagingBackgroundHandler(RemoteMessage message) async { -} \ No newline at end of file +Future firebaseMessagingBackgroundHandler(RemoteMessage message) async {} diff --git a/lib/controllers/notification/notification_manger.dart b/lib/controllers/notification/notification_manger.dart index a568d5d3..3038f784 100644 --- a/lib/controllers/notification/notification_manger.dart +++ b/lib/controllers/notification/notification_manger.dart @@ -2,7 +2,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:test_sa/views/app_style/colors.dart'; -class NotificationManger{ +class NotificationManger { // private constructor to avoid create object NotificationManger._(); @@ -12,43 +12,26 @@ class NotificationManger{ /// onNotificationPressed action when notification pressed to open tap /// onIOSNotificationPressed action when notification pressed /// to open tap in iOS versions older than 10 - static initialisation( - Function(NotificationResponse) onNotificationPressed, - DidReceiveLocalNotificationCallback onIOSNotificationPressed - ) async { - FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = - FlutterLocalNotificationsPlugin(); + static initialisation(Function(NotificationResponse) onNotificationPressed, DidReceiveLocalNotificationCallback onIOSNotificationPressed) async { + FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); // initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project - const AndroidInitializationSettings initializationSettingsAndroid = - AndroidInitializationSettings('app_icon',); + const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings( + 'app_icon', + ); - final DarwinInitializationSettings initializationSettingsDarwin = - DarwinInitializationSettings( - onDidReceiveLocalNotification: onIOSNotificationPressed); + final DarwinInitializationSettings initializationSettingsDarwin = DarwinInitializationSettings(onDidReceiveLocalNotification: onIOSNotificationPressed); - final InitializationSettings initializationSettings = InitializationSettings( - android: initializationSettingsAndroid, - iOS: initializationSettingsDarwin, - macOS: initializationSettingsDarwin); + final InitializationSettings initializationSettings = InitializationSettings(android: initializationSettingsAndroid, iOS: initializationSettingsDarwin, macOS: initializationSettingsDarwin); - await flutterLocalNotificationsPlugin.initialize( - initializationSettings, - onDidReceiveNotificationResponse: onNotificationPressed); + await flutterLocalNotificationsPlugin.initialize(initializationSettings, onDidReceiveNotificationResponse: onNotificationPressed); } // push new notification - static Future showNotification( - { - @required String title, - @required String subtext, - @required int hashcode, - String payload - }) async { - + static Future showNotification({@required String title, @required String subtext, @required int hashcode, String payload}) async { const AndroidNotificationDetails androidChannel = AndroidNotificationDetails( 'com.newtrack.testsa', 'Test SA', - channelDescription:'Push notification service for Test SA', + channelDescription: 'Push notification service for Test SA', importance: Importance.max, priority: Priority.max, playSound: true, @@ -62,8 +45,7 @@ class NotificationManger{ groupKey: 'com.newtrack.testsa', ); - const DarwinNotificationDetails iosNotificationDetails = - DarwinNotificationDetails( + const DarwinNotificationDetails iosNotificationDetails = DarwinNotificationDetails( categoryIdentifier: "testSA", ); @@ -81,5 +63,4 @@ class NotificationManger{ payload: payload, ); } - -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/departments_provider.dart b/lib/controllers/providers/api/departments_provider.dart index 0bcd0f02..b5ca6387 100644 --- a/lib/controllers/providers/api/departments_provider.dart +++ b/lib/controllers/providers/api/departments_provider.dart @@ -2,13 +2,13 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/department.dart'; -class DepartmentsProvider extends ChangeNotifier{ - +class DepartmentsProvider extends ChangeNotifier { //reset provider data - void reset(){ + void reset() { departments = null; stateCode = null; } @@ -18,7 +18,6 @@ class DepartmentsProvider extends ChangeNotifier{ // 500 service not available int stateCode; - // contain user data // when user not login or register _user = null List departments; @@ -28,40 +27,35 @@ class DepartmentsProvider extends ChangeNotifier{ // failed _loading = false bool isLoading; - /// return -2 if request in progress /// return -1 if error happen when sending request /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getDepartment (String host) async { - if(isLoading == true) - return -2; + Future getDepartment(String host) async { + if (isLoading == true) return -2; isLoading = true; notifyListeners(); Response response; - try{ - response = await get( - Uri.parse(host + URLs.getDepartments), - headers: { - "Content-Type":"application/json; charset=utf-8" - } - ); - } catch(error) { + try { + response = await ApiManager.instance.post(URLs.getDepartments, body: { + "pageSize": 50, + // if(title != null && title.isNotEmpty) "name":title, + }); + } catch (error) { isLoading = false; stateCode = -1; notifyListeners(); return -1; } stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List listJson = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", "")); + List listJson = json.decode(response.body)["data"]; departments = listJson.map((department) => Department.fromJson(department)).toList(); } isLoading = false; notifyListeners(); return response.statusCode; } - -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/device_transfer_provider.dart b/lib/controllers/providers/api/device_transfer_provider.dart index 1d433c11..cdd685bd 100644 --- a/lib/controllers/providers/api/device_transfer_provider.dart +++ b/lib/controllers/providers/api/device_transfer_provider.dart @@ -2,21 +2,33 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/device/device_transfer.dart'; import 'package:test_sa/models/device/device_transfer_info.dart'; +import 'package:test_sa/models/device/device_transfer_search.dart'; import 'package:test_sa/models/user.dart'; -class DeviceTransferProvider extends ChangeNotifier{ +import '../../../models/hospital.dart'; +class DeviceTransferProvider extends ChangeNotifier { // number of items call in each request - final pageItemNumber = 50; + final pageItemNumber = 12; + + DeviceTransferSearch deviceTransferSearch = DeviceTransferSearch(); //reset provider data - void reset(){ + void reset() { items = null; nextPage = true; stateCode = null; + hospital = null; + building = null; + floor = null; + department = null; + room = ""; + startDate = null; + endDate = null; } // state code of current request to defied error message @@ -35,136 +47,224 @@ class DeviceTransferProvider extends ChangeNotifier{ // failed _loading = false bool isLoading; + Hospital hospital; + Buildings building; + Floors floor; + Departments department; + String room; + DateTime startDate; + DateTime endDate; + /// return -2 if request in progress /// return -1 if error happen when sending request /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getRequests ({ + Future getRequests({ @required String host, @required User user, }) async { - if(isLoading == true) - return -2; + if (isLoading == true) return -2; isLoading = true; - - // isLoading = false; - // stateCode = 200; - // items = []; - // items.addAll(List.generate(20, (index) => DeviceTransfer( - // title: "ddddd", - // id: "5", - // device: Device(id: "1",brand: "brand",model: "model"), - // destinationClient: Hospital(name: "hospital name",id: "1"), - // destinationDepartment: Department(id: "5",name: "destination Department"), - // senderDepartment: Department(id: "5",name: "sender Department"), - // userId: "5" - // ))); - // notifyListeners(); - // return 200; + if (items?.isEmpty ?? true) notifyListeners(); Response response; - try{ - response = await get( - Uri.parse( - "$host${URLs.getDeviceTransfer}?uid=${user.id}" - "&token=${user.token}&page=${(items?.length ?? 0) ~/pageItemNumber}" - ), - headers: { - "Content-Type":"application/json; charset=utf-8" - } + try { + Map body = {}; + body["pageNumber"] = (items?.length ?? 0) ~/ pageItemNumber + 1; + body["pageSize"] = pageItemNumber; + body.addAll(deviceTransferSearch.toMap()); + + response = await ApiManager.instance.post( + URLs.getDeviceTransfer, + body: body, ); + stateCode = response.statusCode; - if(stateCode >= 200 && stateCode < 300) { + if (stateCode >= 200 && stateCode < 300) { // client's request was successfully received - List listJson = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", "")); - List itemsPage = listJson.map( - (request) => DeviceTransfer.fromJson(request)).toList(); + List listJson = json.decode(response.body)["data"]; + List itemsPage = listJson.map((request) => DeviceTransfer.fromJson(request)).toList(); items ??= []; - items.addAll(itemsPage); - if(itemsPage.length == pageItemNumber){ + items.addAll(itemsPage.toSet().toList()); + sortMostRecent(items, deviceTransferSearch.mostRecent); + + print(listJson); + if (itemsPage.length == pageItemNumber) { nextPage = true; - }else{ + } else { nextPage = false; } } isLoading = false; notifyListeners(); return response.statusCode; - - } catch(error) { + } catch (error) { isLoading = false; stateCode = -1; notifyListeners(); return -1; } + } + void sortMostRecent(List transfer, bool mostRecent) { + if (mostRecent != null) { + transfer.sort((prev, next) => + (mostRecent ?? false) ? DateTime.tryParse(next.createdOn).compareTo(DateTime.tryParse(prev.createdOn)) : DateTime.tryParse(prev.createdOn).compareTo(DateTime.tryParse(next.createdOn))); + } } - Future createRequest ({ + Future getRequestById({int assetTransferId}) async { + Response response; + try { + response = await ApiManager.instance.get( + URLs.getAssetTransferById + "?assetTransferId=$assetTransferId", + enableToastMessage: false, + ); + if (response.statusCode >= 200 && response.statusCode < 300) { + return DeviceTransfer.fromJson(json.decode(response.body)["data"]); + } + return null; + } catch (error) { + print(error); + return null; + } + } + + Future createRequest({ @required String host, @required User user, @required DeviceTransfer model, }) async { - Map body = { - "uid": user.id.toString(), - "token": user.token ?? "", - "serial_id": model.device.id ?? "", - "destination_client": model.receiver.client.id ?? "", - "destination_department": model.receiver.department.id ?? "", + Map body = { + "id": 0, + "assetId": model.device.id ?? "", + "destSiteId": hospital.id ?? "", + "destDepartmentId": department.id ?? "", + "senderSiteId": model.sender.client.id ?? "", + // "transferNo": 0, + // "transferCode": "string", + "destBuildingId": building?.id, + "destFloorId": floor.id, + "destRoom": room, + ///// + "senderBuildingId": model.device.destBuildingId, + "senderFloorId": model.device.destFloorId, + "senderDepartmentId": model.device.destDepartmentId, + "senderRoom": model.device.destRoom, + // "senderAssignedEmployeeId": "string", + // "senderMachineStatusId": 0, + // "senderComment": "string", + // "senderStartDate": "2023-06-11T09:21:56.453Z", + // "senderEndDate": "2023-06-11T09:21:56.453Z", + // "senderWorkingHours": "string", + // "senderTravelingHours": "string", + // "senderAttachmentName": "string", + // "receiverAssignedEmployeeId": "string", + // "receiverMachineStatusId": 0, + // "receiverComment": "string", + // "receiverStartDate": "2023-06-11T09:21:56.453Z", + // "receiverEndDate": "2023-06-11T09:21:56.453Z", + // "receiverWorkingHours": "string", + // "receiverTravelingHours": "string", + // "receiverAttachmentName": "string" }; - Response response; - try{ - response = await post( - Uri.parse( - host+URLs.requestDeviceTransfer), - body: body, - ); + try { + response = await ApiManager.instance.post(URLs.requestDeviceTransfer, body: body); stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { - if(items != null) { - items.insert( - 0, - DeviceTransfer.fromJson( - json.decode(utf8.decode(response.bodyBytes))[0] - ) - ); + if (response.statusCode >= 200 && response.statusCode < 300) { + if (items != null) { + items.insert(0, DeviceTransfer.fromJson(json.decode(utf8.decode(response.bodyBytes))[0])); + reset(); notifyListeners(); } } return response.statusCode; - - } catch(error) { + } catch (error) { return -1; } - } - Future updateRequest ({ + Future updateRequest({ @required String host, @required User user, @required bool isSender, - @required String requestId, + @required int requestId, @required DeviceTransfer oldModel, @required DeviceTransferInfo newModel, }) async { - - Map body = { - "uid": user.id.toString(), - "token": user.token ?? "", - "current_user": user.id ?? "", + Map body = { + "id": oldModel.id, + "assetId": oldModel.device.id ?? "", + "senderSiteId": oldModel.sender.client.id, + "destSiteId": oldModel.receiver.client.id, + "destDepartmentId": oldModel.receiver.department.id, }; - - body.addAll(newModel.toJson(isSender)); + + if (isSender) { + body.addAll({ + "senderSiteId": newModel.client.id, + "senderDepartmentId": newModel.department.id, + "senderAssignedEmployeeId": newModel.userId, + "senderMachineStatusId": newModel.status.id, + "senderComment": newModel.comment, + "senderWorkingHours": newModel.workingHours, + "senderStartDate": newModel.timer?.startAt?.toIso8601String(), + "senderEndDate": newModel.timer?.endAt?.toIso8601String(), + "senderTravelingHours": newModel.travelingHours, + "senderAttachmentName": newModel?.signature ?? "", + "destSiteId": oldModel.receiver.client.id, + "destDepartmentId": oldModel.receiver.department.id, + "receiverAssignedEmployeeId": oldModel.receiver.userId, + "receiverMachineStatusId": oldModel.receiver.status.id ?? "", + "receiverComment": oldModel.receiver.comment, + "receiverWorkingHours": oldModel.receiver.workingHours, + "receiverStartDate": oldModel.receiver.timer?.startAt?.toIso8601String(), + "receiverEndDate": oldModel.receiver.timer?.endAt?.toIso8601String(), + "receiverTravelingHours": oldModel.receiver.travelingHours, + "receiverAttachmentName": oldModel.receiver?.signature ?? "", + }); + } else { + body.addAll({ + "senderSiteId": oldModel.sender.client.id, + "senderDepartmentId": oldModel.sender.department.id, + "senderAssignedEmployeeId": oldModel.sender.userId, + "senderMachineStatusId": oldModel.sender.status.id, + "senderComment": oldModel.sender.comment, + "senderWorkingHours": oldModel.sender.workingHours, + "senderStartDate": oldModel.sender.timer?.startAt?.toIso8601String(), + "senderEndDate": oldModel.sender.timer?.endAt?.toIso8601String(), + "senderTravelingHours": oldModel.sender.travelingHours, + "senderAttachmentName": oldModel.sender?.signature ?? "", + "destSiteId": newModel.client.id, + "destDepartmentId": newModel.department.id, + "receiverAssignedEmployeeId": newModel.userId, + "receiverMachineStatusId": newModel.status?.id ?? "", + "receiverComment": newModel.comment, + "receiverWorkingHours": newModel.workingHours, + "receiverStartDate": newModel.timer?.startAt?.toIso8601String(), + "receiverEndDate": newModel.timer?.endAt?.toIso8601String(), + "receiverTravelingHours": newModel.travelingHours, + "receiverAttachmentName": newModel?.signature ?? "", + }); + } + + //body.addAll(newModel.toJson(isSender)); + print(body); Response response; - try{ - response = await post( - Uri.parse("$host${URLs.updateDeviceTransfer}/$requestId"), - body: body, - ); + try { + response = await ApiManager.instance.put(URLs.updateDeviceTransfer, body: body); + + print(response.body); + print("${newModel.signature}.png"); + // response = await post( + // Uri.parse("$host${URLs.updateDeviceTransfer}/$requestId"), + // body: body, + // ); + stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { reset(); // oldModel.fromDeviceTransfer( // DeviceTransfer.fromJson( @@ -174,10 +274,8 @@ class DeviceTransferProvider extends ChangeNotifier{ notifyListeners(); } return response.statusCode; - - } catch(error) { + } catch (error) { return -1; } - } -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/devices_provider.dart b/lib/controllers/providers/api/devices_provider.dart index b55d1733..4908b573 100644 --- a/lib/controllers/providers/api/devices_provider.dart +++ b/lib/controllers/providers/api/devices_provider.dart @@ -2,33 +2,41 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/device/device.dart'; +import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/user.dart'; -class DevicesProvider extends ChangeNotifier{ - +class DevicesProvider extends ChangeNotifier { //reset provider data - void reset(){ - _devices = null; + void reset() { + _devices = []; _stateCode = null; } + final pageItemNumber = 10; + bool nextPage = true; + // state code of current request to defied error message // like 400 customer request failed // 500 service not available int _stateCode; + int get stateCode => _stateCode; - List _devices; + List _devices = []; + List get devices => _devices; // when categories in-process _loading = true // done _loading = true // failed _loading = false bool _loading; + bool get isLoading => _loading; - set isLoading(bool isLoading){ + + set isLoading(bool isLoading) { _loading = isLoading; notifyListeners(); } @@ -38,34 +46,39 @@ class DevicesProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getEquipment ({ + Future getEquipment({ @required String host, @required User user, - @required String hospitalId + @required int hospitalId, + String serialNumber, + String number, }) async { - if(_loading == true) - return -2; + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - response = await get( - Uri.parse(host + URLs.getEquipment+"?client=$hospitalId"), - headers: { - "Content-Type":"application/json; charset=utf-8" - } - ); - } catch(error) { + try { + response = await ApiManager.instance.post(URLs.getEquipment, body: { + "pageSize": pageItemNumber, + "pageNumber": devices.length ~/ pageItemNumber + 1, + "siteId": hospitalId, + if (serialNumber?.isEmpty == false) "assetSerialNumber": serialNumber, + if (number?.isEmpty == false) "assetNo": number, + }); + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return -1; } _stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List equipmentListJson = json.decode(utf8.decode(response.bodyBytes)); - _devices = equipmentListJson.map((device) => Device.fromJson(device)).toList(); + List equipmentListJson = json.decode(response.body)["data"]; + _devices.addAll(equipmentListJson.map((device) => Device.fromJson(device, startKeyWithDest: false)).toList()); + nextPage = true; + } else { + nextPage = false; } _loading = false; notifyListeners(); @@ -77,66 +90,93 @@ class DevicesProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future> getDevicesList ({ + Future> getDevicesList({ @required String host, @required User user, - @required String hospitalId, + @required int hospitalId, String serialNumber, String number, }) async { Response response; - try{ - response = await get( - Uri.parse("$host${URLs.getEquipment}?client=$hospitalId" - "${serialNumber?.isEmpty == false ? "&name=$serialNumber" :""}" - "${number?.isEmpty == false ? "&number=$number" : ""}" - ), - ); - List page = []; - if(response.statusCode >= 200 && response.statusCode < 300) { + try { + response = await ApiManager.instance.post(URLs.getEquipment, body: { + "pageSize": pageItemNumber, + "pageNumber": devices.length ~/ pageItemNumber + 1, + "siteId": devices.length ~/ pageItemNumber + 1, + if (serialNumber?.isEmpty == false) "assetSerialNumber": serialNumber, + if (number?.isEmpty == false) "assetNo": number, + }); + // response = await get( + // Uri.parse("$host${URLs.getEquipment}?siteId=$hospitalId" + // "${serialNumber?.isEmpty == false ? "&assetSerialNumber=$serialNumber" :""}" + // "${number?.isEmpty == false ? "&assetNo=$number" : ""}" + // ), + // ); + List page = []; + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); - page = categoriesListJson.map((device) => Device.fromJson(device)).toList(); + List equipmentListJson = json.decode(response.body)["data"]; + page = equipmentListJson.map((device) => Device.fromJson(device, startKeyWithDest: false)).toList(); + _devices.addAll(equipmentListJson.map((device) => Device.fromJson(device, startKeyWithDest: false)).toList()); + notifyListeners(); } return page; - } catch(error) { + } catch (error) { return []; } - } - /// return -2 if request in progress - /// return -1 if error happen when sending request - /// return state code if request complete may be 200, 404 or 403 - /// for more details check http state manager - /// lib\controllers\http_status_manger\http_status_manger.dart - Future> getDevicesListBySN ({ - @required String host, - @required User user, - @required String hospitalId, - @required String sn + Future> getModels({ + String code, }) async { Response response; - try{ - response = await get( - Uri.parse(host + URLs.getEquipment+"?client=$hospitalId" - + ( sn == null || sn.isEmpty ? "" : "&serial_qr=$sn" )), + try { + response = await ApiManager.instance.get( + URLs.getModels + "?code=$code", ); - - _stateCode = response.statusCode; - List _page = []; - if(response.statusCode >= 200 && response.statusCode < 300) { + List page = []; + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); - _page = categoriesListJson.map((device) => Device.fromJson(device)).toList(); + List categoriesListJson = json.decode(response.body)["data"]; + page = categoriesListJson + .map((json) => Lookup( + name: json["modelDefCode"], + id: json["id"], + value: json["id"], + )) + .toList(); } - return _page; - } catch(error) { - _loading = false; - _stateCode = -1; - notifyListeners(); + return page; + } catch (error) { return []; } - } -} \ No newline at end of file + +// /// return -2 if request in progress +// /// return -1 if error happen when sending request +// /// return state code if request complete may be 200, 404 or 403 +// /// for more details check http state manager +// /// lib\controllers\http_status_manger\http_status_manger.dart +// Future> getDevicesListBySN({@required String host, @required User user, @required int hospitalId, @required String sn}) async { +// Response response; +// try { +// response = await get( +// Uri.parse(URLs.getEquipment + "?client=$hospitalId" + (sn == null || sn.isEmpty ? "" : "&serial_qr=$sn")), +// ); +// +// _stateCode = response.statusCode; +// List _page = []; +// if (response.statusCode >= 200 && response.statusCode < 300) { +// // client's request was successfully received +// List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); +// _page = categoriesListJson.map((device) => Device.fromJson(device)).toList(); +// } +// return _page; +// } catch (error) { +// _loading = false; +// _stateCode = -1; +// notifyListeners(); +// return []; +// } +// } +} diff --git a/lib/controllers/providers/api/gas_refill_provider.dart b/lib/controllers/providers/api/gas_refill_provider.dart index 7dba6a8c..40a96203 100644 --- a/lib/controllers/providers/api/gas_refill_provider.dart +++ b/lib/controllers/providers/api/gas_refill_provider.dart @@ -1,21 +1,28 @@ import 'dart:convert'; +import 'dart:developer'; import 'package:flutter/cupertino.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/gas_refill/gas_refill_model.dart'; +import 'package:test_sa/models/hospital.dart'; +import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/models/user.dart'; -class GasRefillProvider extends ChangeNotifier{ - +class GasRefillProvider extends ChangeNotifier { // number of items call in each request - final pageItemNumber = 50; + final pageItemNumber = 12; //reset provider data - void reset(){ + void reset() { items = null; nextPage = true; stateCode = null; + hospital = null; + building = null; + floor = null; + department = null; } // state code of current request to defied error message @@ -39,134 +46,169 @@ class GasRefillProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getRequests ({ + Future getRequests({ @required String host, @required User user, + bool mostRecent, }) async { - if(isLoading == true) - return -2; + if (isLoading == true) return -2; isLoading = true; + if (items?.isEmpty ?? true) notifyListeners(); Response response; - try{ - response = await get( - Uri.parse( - "$host${URLs.getGasRefill}?uid=${user.id}" - "&token=${user.token}&page=${(items?.length ?? 0) ~/pageItemNumber}" - ), - headers: { - "Content-Type":"application/json; charset=utf-8" - } - ); - stateCode = response.statusCode; - if(stateCode >= 200 && stateCode < 300) { - // client's request was successfully received - List requestsListJson = json.decode(utf8.decode(response.bodyBytes)); - List itemsPage = requestsListJson.map( - (request) => GasRefillModel.fromJson(request)).toList(); + + Map body = {}; + body["pageNumber"] = (items?.length ?? 0) ~/ pageItemNumber + 1; + body["pageSize"] = pageItemNumber; + print("url:${URLs.getGasRefill}:body:$body"); + + response = await ApiManager.instance.post( + URLs.getGasRefill, + body: body, + ); + stateCode = response.statusCode; + if (stateCode >= 200 && stateCode < 300) { + // client's request was successfully received + List requestsListJson = json.decode(response.body)["data"]; + List itemsPage = requestsListJson.map((request) => GasRefillModel.fromJson(request)).toList(); + if (mostRecent != null) { + items = []; + } else { items ??= []; - items.addAll(itemsPage); - if(itemsPage.length == pageItemNumber){ - nextPage = true; - }else{ - nextPage = false; - } } + items.addAll(itemsPage); + sortMostRecent(items, mostRecent); + if (itemsPage.length == pageItemNumber) { + nextPage = true; + } else { + nextPage = false; + } + } + try { isLoading = false; notifyListeners(); return response.statusCode; - - } catch(error) { + } catch (error) { isLoading = false; stateCode = -1; notifyListeners(); return -1; } + } + void sortMostRecent(List models, bool mostRecent) { + if (mostRecent != null) { + models.sort((prev, next) => (mostRecent ?? false) ? next.title.compareTo(prev.title) : prev.title.compareTo(next.title)); + } } - Future createModel ({ + Future createModel({ @required String host, @required User user, @required GasRefillModel model, }) async { - Map body = { + Map body = { "uid": user.id.toString(), "token": user.token ?? "", - "title": model.title ?? "", - "status": "0",//model.status.value.toString(), + "site": hospital?.toMap(), + "building": {"id": building?.id, "name": building?.name, "value": building?.value}, + "floor": {"id": floor?.id, "name": floor?.name, "value": floor?.value}, + if (expectedDateTime != null) "expectedDate": expectedDateTime?.toIso8601String(), + if (expectedDateTime != null) "expectedTime": expectedDateTime?.toIso8601String(), + if (timer?.startAt != null) "startDate": timer.startAt.toIso8601String(), + if (timer?.startAt != null) "startTime": timer.startAt.toIso8601String(), + if (timer?.endAt != null) "endDate": timer.endAt.toIso8601String(), + if (timer?.endAt != null) "endTime": timer.endAt.toIso8601String(), + "department": {"id": department?.id, "departmentName": department?.name, "departmentCode": "", "ntCode": ""}, + "GazRefillNo": "GR-${DateTime.now().toString().split(" ").first}", + "status": model.status.toMap(), }; - - body["details"] = jsonEncode(model.details.map((model) => { - "type": model.type.id?.toString(), - "size": model.cylinderSize?.id.toString(), - "requsted_qty": model.requestedQuantity.toString(), - }).toList()); + body["gazRefillDetails"] = model.details + .map((model) => { + "gasType": model.type.toMap(), + "cylinderSize": model.cylinderSize.toMap(), + "cylinderType": model.cylinderType.toMap(), + "requestedQty": model.requestedQuantity, + }) + .toList(); Response response; - try{ - response = await post( - Uri.parse( - host+URLs.requestGasRefill), - body: body, - ); - + try { + response = await ApiManager.instance.post(URLs.requestGasRefill, body: body); stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { - if(items != null) { - items.insert( - 0, - GasRefillModel.fromJson( - json.decode(utf8.decode(response.bodyBytes))[0] - ) - ); + if (response.statusCode >= 200 && response.statusCode < 300) { + if (items != null) { + reset(); notifyListeners(); } } return response.statusCode; - - } catch(error) { + } catch (error) { + print(error); return -1; } - } - Future updateModel ({ + Future updateModel({ @required String host, @required User user, @required GasRefillModel oldModel, @required GasRefillModel newModel, }) async { - Map body = { - "uid": user.id.toString(), - "token": user.token ?? "", - "title": newModel.title ?? "", - "status": newModel.status.id.toString(), + Map body = { + "id": newModel.id, + "gazRefillNo": newModel.title ?? "", + "status": newModel.status.toMap(), + "expectedDate": newModel.expectedDate?.toIso8601String(), + "expectedTime": newModel.expectedDate?.toIso8601String(), + if (timer?.startAt != null) "startDate": timer.startAt.toIso8601String(), + if (timer?.startAt != null) "startTime": timer.startAt.toIso8601String(), + if (timer?.endAt != null) "endDate": timer.endAt.toIso8601String(), + if (timer?.endAt != null) "endTime": timer.endAt.toIso8601String(), + // "workingHours": ((endDate?.difference(startDate)?.inMinutes ?? 0) / 60), + 'workingHours': timer.durationInSecond != null ? timer.durationInSecond / 60 / 60 : newModel.workingHours, + "assignedEmployee": oldModel?.assignedEmployee?.id == null ? null : oldModel?.assignedEmployee?.toJson(), + "site": hospital?.toMap(), + "building": building?.toJson(includeFloors: false), + "floor": floor?.toJson(includeDepartments: false), + "department": department?.toJson(), + "engSignature": newModel.signatureEngineer, + "nurseSignature": newModel.signatureNurse, }; - body["details"] = jsonEncode(newModel.details.map((model) => { - "type": model.type.id.toString(), - "size": model.cylinderSize.id.toString(), - "requsted_qty": model.requestedQuantity.toString(), - "deliverd_qty": model.deliveredQuantity.toString(), - }).toList()); - - Response response; - try{ - response = await post( - Uri.parse("$host${URLs.updateGasRefill}/${newModel.id}"), - body: body, - ); - - stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { - oldModel.fromGasRefillModel(newModel); - notifyListeners(); - } - return response.statusCode; - - } catch(error) { - return -1; - } - + body["gazRefillDetails"] = newModel.details + .map((model) => { + "gasType": model.type.toMap(), + "cylinderSize": model.cylinderSize.toMap(), + "cylinderType": model.cylinderType.toMap(), + "requestedQty": model.requestedQuantity, + "deliverdQty": model.deliveredQuantity, + }) + .toList(); + log(body.toString()); + return -1; + // Response response; + // try { + // response = await ApiManager.instance.put(URLs.updateGasRefill, body: body); + // // response = await post( + // // Uri.parse("$host${URLs.updateGasRefill}/${newModel.id}"), + // // body: body, + // // ); + // + // stateCode = response.statusCode; + // if (response.statusCode >= 200 && response.statusCode < 300) { + // oldModel.fromGasRefillModel(newModel); + // notifyListeners(); + // } + // return response.statusCode; + // } catch (error) { + // return -1; + // } } -} \ No newline at end of file + + Hospital hospital; + Buildings building; + Floors floor; + Departments department; + DateTime expectedDateTime; + TimerModel timer; +} diff --git a/lib/controllers/providers/api/hospitals_provider.dart b/lib/controllers/providers/api/hospitals_provider.dart index df70994f..da0e2cd7 100644 --- a/lib/controllers/providers/api/hospitals_provider.dart +++ b/lib/controllers/providers/api/hospitals_provider.dart @@ -3,17 +3,17 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/hospital.dart'; import 'package:test_sa/models/user.dart'; -class HospitalsProvider extends ChangeNotifier{ - +class HospitalsProvider extends ChangeNotifier { // number of items call in each request - final pageItemNumber = 50; + final pageItemNumber = 12; //reset provider data - void reset(){ + void reset() { _hospitals = null; _stateCode = null; } @@ -22,23 +22,28 @@ class HospitalsProvider extends ChangeNotifier{ // like 400 customer request failed // 500 service not available int _stateCode; + int get stateCode => _stateCode; // true if there is next page in product list and false if not bool _nextPage = true; + bool get nextPage => _nextPage; // contain user data // when user not login or register _user = null List _hospitals; + List get hospitals => _hospitals; // when categories in-process _loading = true // done _loading = true // failed _loading = false bool _loading; + bool get isLoading => _loading; - set isLoading(bool isLoading){ + + set isLoading(bool isLoading) { _loading = isLoading; notifyListeners(); } @@ -48,77 +53,101 @@ class HospitalsProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getHospitals ({String host,User user,String title}) async { - if(_loading == true) - return -2; + Future getHospitals({String host, User user, String title}) async { + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - response = await get( - Uri.parse( - host + URLs.getHospitals - + "?page=${(_hospitals?.length ?? 0) ~/pageItemNumber}" - + ( title == null || title.isEmpty ? "" : "&name=$title" ) - ), - headers: { - "Content-Type":"application/json; charset=utf-8" - } - ); + try { + response = await ApiManager.instance.post(URLs.getHospitals, body: { + "pageNumber": (hospitals?.length ?? 0) ~/ pageItemNumber + 1, + "pageSize": 50, + if (title != null && title.isNotEmpty) "name": title, + }); _stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); - List _page = categoriesListJson.map((category) => Hospital.fromJson(category)).toList(); - if(hospitals == null) - _hospitals = []; + List categoriesListJson = json.decode(response.body)["data"]; + List _page = categoriesListJson.map((category) => Hospital.fromJson(category)).toList(); + if (hospitals == null) _hospitals = []; _hospitals.addAll(_page); - if(_page.length >= pageItemNumber){ + if (_page.length >= pageItemNumber) { _nextPage = true; - }else{ + } else { _nextPage = false; } } _loading = false; notifyListeners(); return response.statusCode; - } catch(error) { + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return -1; } - } - Future> getHospitalsList ({String host,User user,String title}) async { + Future> getHospitalsList({String host, User user, String title}) async { Response response; - try{ - - response = await get( - Uri.parse(host + URLs.getHospitals - + ( title == null || title.isEmpty ? "" : "?name=$title" )), - headers: { - "Content-Type":"application/json; charset=utf-8" - } - ); + try { + response = await ApiManager.instance.post(URLs.getHospitals, body: { + "pageSize": 50, + if (title != null && title.isNotEmpty) "name": title, + }); + // response = await get( + // Uri.parse(host + URLs.getHospitals + // + ( title == null || title.isEmpty ? "" : "?name=$title" )), + // headers: { + // "Content-Type":"application/json; charset=utf-8" + // } + // ); _stateCode = response.statusCode; - List _page = []; - if(response.statusCode >= 200 && response.statusCode < 300) { + List _page = []; + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); + List categoriesListJson = json.decode(response.body)["data"]; _page = categoriesListJson.map((category) => Hospital.fromJson(category)).toList(); } return _page; - } catch(error) { + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return []; } - } -} \ No newline at end of file + Future> getHospitalsListByVal({String searchVal = ""}) async { + Response response; + try { + if (searchVal.isNotEmpty) { + searchVal = "?searchText=$searchVal"; + } + response = await ApiManager.instance.get(URLs.getHospitalsAutoComplete + searchVal); + // response = await get( + // Uri.parse(host + URLs.getHospitals + // + ( title == null || title.isEmpty ? "" : "?name=$title" )), + // headers: { + // "Content-Type":"application/json; charset=utf-8" + // } + // ); + _stateCode = response.statusCode; + + List _page = []; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + _page = categoriesListJson.map((category) => Hospital.fromJson(category)).toList(); + } + return _page; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return []; + } + } +} diff --git a/lib/controllers/providers/api/notifications_provider.dart b/lib/controllers/providers/api/notifications_provider.dart index d21ec77b..b7683ab5 100644 --- a/lib/controllers/providers/api/notifications_provider.dart +++ b/lib/controllers/providers/api/notifications_provider.dart @@ -6,13 +6,12 @@ import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/app_notification.dart'; import 'package:test_sa/models/user.dart'; -class NotificationsProvider extends ChangeNotifier{ - +class NotificationsProvider extends ChangeNotifier { // number of items call in each request - final pageItemNumber = 20; + final pageItemNumber = 12; //reset provider data - void reset(){ + void reset() { notifications = null; nextPage = true; stateCode = null; @@ -34,58 +33,50 @@ class NotificationsProvider extends ChangeNotifier{ // failed _loading = false bool isLoading; - /// return -2 if request in progress /// return -1 if error happen when sending request /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getNotifications ({ + Future getNotifications({ @required String host, @required User user, - @required String hospitalId, + @required int hospitalId, }) async { - if(isLoading == true) - return -2; + if (isLoading == true) return -2; isLoading = true; notifyListeners(); Response response; - // userId = 397.toString(); // testing id to view data - try{ + // userId = 397.toString(); // testing id to view data + try { response = await get( - Uri.parse(host+URLs.getNotifications - +"?uid=${user.id}" - "&token=${user.token}" - "&page=${(notifications?.length ?? 0) ~/pageItemNumber}"), - headers: { - "Content-Type":"application/json; charset=utf-8" - } - ); + Uri.parse(URLs.getNotifications + + "?uid=${user.id}" + "&token=${user.token}" + "&page=${(notifications?.length ?? 0) ~/ pageItemNumber}"), + headers: {"Content-Type": "application/json; charset=utf-8"}); stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received List requestsListJson = json.decode(utf8.decode(response.bodyBytes)); - List _serviceRequestsPage = requestsListJson.map( - (request) => AppNotification.fromJson(request)).toList(); - if(notifications == null) - notifications = []; + List _serviceRequestsPage = requestsListJson.map((request) => AppNotification.fromJson(request)).toList(); + if (notifications == null) notifications = []; notifications.addAll(_serviceRequestsPage); - if(_serviceRequestsPage.length == pageItemNumber){ + if (_serviceRequestsPage.length == pageItemNumber) { nextPage = true; - }else{ + } else { nextPage = false; } } isLoading = false; notifyListeners(); return response.statusCode; - } catch(error) { + } catch (error) { isLoading = false; stateCode = -1; notifyListeners(); return -1; } - } /// return -2 if request in progress @@ -93,35 +84,26 @@ class NotificationsProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future> getRecentNotifications ({ + Future> getRecentNotifications({ @required String host, @required User user, }) async { Response response; //userId = 397.toString(); // testing id to view data - try{ - response = await get( - Uri.parse(host+URLs.getNotifications - +"?uid=${user.id}&token=${user.token}"), - headers: { - "Content-Type":"application/json; charset=utf-8" - } - ); + try { + response = await get(Uri.parse(host + URLs.getNotifications + "?uid=${user.id}&token=${user.token}"), headers: {"Content-Type": "application/json; charset=utf-8"}); stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received List requestsListJson = json.decode(utf8.decode(response.bodyBytes)); - List _recentNotifications = requestsListJson.map( - (request) => AppNotification.fromJson(request)).toList(); + List _recentNotifications = requestsListJson.map((request) => AppNotification.fromJson(request)).toList(); return _recentNotifications; } return null; - - } catch(error) { + } catch (error) { return null; } - } -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/parts_provider.dart b/lib/controllers/providers/api/parts_provider.dart index 6f763f77..fbe7a319 100644 --- a/lib/controllers/providers/api/parts_provider.dart +++ b/lib/controllers/providers/api/parts_provider.dart @@ -1,19 +1,19 @@ import 'dart:convert'; -import 'package:test_sa/controllers/api_routes/urls.dart'; -import 'package:test_sa/models/part.dart'; -import 'package:test_sa/models/user.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/part.dart'; +import 'package:test_sa/models/user.dart'; -class PartsProvider extends ChangeNotifier{ - +class PartsProvider extends ChangeNotifier { // number of items call in each request - final pageItemNumber = 50; + final pageItemNumber = 20; //reset provider data - void reset(){ + void reset() { _parts = null; _stateCode = null; } @@ -22,23 +22,28 @@ class PartsProvider extends ChangeNotifier{ // like 400 customer request failed // 500 service not available int _stateCode; + int get stateCode => _stateCode; // true if there is next page in product list and false if not bool _nextPage = true; + bool get nextPage => _nextPage; // contain user data // when user not login or register _user = null List _parts; + List get parts => _parts; // when categories in-process _loading = true // done _loading = true // failed _loading = false bool _loading; + bool get isLoading => _loading; - set isLoading(bool isLoading){ + + set isLoading(bool isLoading) { _loading = isLoading; notifyListeners(); } @@ -48,48 +53,36 @@ class PartsProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getParts ({String host,User user,String title}) async { - if(_loading == true) - return -2; + Future getParts({String host, User user, String title}) async { + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - response = await get( - Uri.parse( - host + URLs.getPartNumber - + "?page=${(_parts?.length ?? 0) ~/pageItemNumber}" - + ( title == null || title.isEmpty ? "" : "&name=$title" ) - ), - headers: { - "Content-Type":"application/json; charset=utf-8" - } - ); + try { + response = await ApiManager.instance.post(URLs.getPartNumber, body: {if (title != null && title.isNotEmpty) "partName": title}); _stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); - List _page = categoriesListJson.map((part) => Part.fromJson(part)).toList(); - if(parts == null) - _parts = []; + List _page = categoriesListJson.map((part) => Part.fromJson(part)).toList(); + if (parts == null) _parts = []; _parts.addAll(_page); - if(_page.length >= pageItemNumber){ + if (_page.length >= pageItemNumber) { _nextPage = true; - }else{ + } else { _nextPage = false; } } _loading = false; notifyListeners(); return response.statusCode; - } catch(error) { + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return -1; } - } /// return -2 if request in progress @@ -97,30 +90,23 @@ class PartsProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future> getPartsList ({String host,User user,String title}) async { + Future> getPartsList({String host, User user, String title}) async { Response response; - try{ - - response = await get( - Uri.parse( - host + URLs.getPartNumber - + ( title == null || title.isEmpty ? "" : "?name=$title" ) - ), - headers: { - "Content-Type":"application/json; charset=utf-8" - } - ); - List _page = []; - if(response.statusCode >= 200 && response.statusCode < 300) { + try { + if (int.tryParse(title) != null) { + response = await ApiManager.instance.post(URLs.getPartNumber, body: {if (title != null && title.isNotEmpty) "partNo": title}); + } else { + response = await ApiManager.instance.post(URLs.getPartNumber, body: {if (title != null && title.isNotEmpty) "partName": title}); + } + List page = []; + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); - _page = categoriesListJson.map((part) => Part.fromJson(part)).toList(); + List categoriesListJson = json.decode(response.body)["data"]; + page = categoriesListJson.map((part) => Part.fromJson(part)).toList(); } - return _page; - } catch(error) { + return page; + } catch (error) { return []; } - } - -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/preventive_maintenance_visits_provider.dart b/lib/controllers/providers/api/preventive_maintenance_visits_provider.dart index 14103fd6..59bf347a 100644 --- a/lib/controllers/providers/api/preventive_maintenance_visits_provider.dart +++ b/lib/controllers/providers/api/preventive_maintenance_visits_provider.dart @@ -1,20 +1,20 @@ import 'dart:convert'; +import 'package:flutter/cupertino.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/user.dart'; import 'package:test_sa/models/visits/visit.dart'; import 'package:test_sa/models/visits/visits_group.dart'; import 'package:test_sa/models/visits/visits_search.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:http/http.dart'; - -class PreventiveMaintenanceVisitsProvider extends ChangeNotifier{ +class PreventiveMaintenanceVisitsProvider extends ChangeNotifier { // number of items call in each request - final pageItemNumber = 50; + final pageItemNumber = 10; //reset provider data - void reset(){ + void reset() { visits = null; nextPage = true; stateCode = null; @@ -43,47 +43,37 @@ class PreventiveMaintenanceVisitsProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getVisits ({ + Future getVisits({ @required String host, @required User user, - // VisitsSearch visitsSearch, + // VisitsSearch visitsSearch, }) async { - if(isLoading == true) - return -2; + if (isLoading == true) return -2; isLoading = true; Response response; //userId = 397.toString(); // testing id to view data - try{ + try { response = await get( Uri.parse( - host + URLs.getPreventiveMaintenanceVisits - +"?uid=${user.id}" - "&token=${user.token}" - "&page=${(visits?.length ?? 0) ~/pageItemNumber}" - +visitsSearch?.toSearchString() ?? "" + "${host + URLs.getPreventiveMaintenanceVisits}?uid=${user.id}&token=${user.token}&page=${(visits?.length ?? 0) ~/ pageItemNumber}${visitsSearch?.toMap()}", ), - headers: { - "Content-Type":"application/json; charset=utf-8" - } - ); - } catch(error) { + headers: {"Content-Type": "application/json; charset=utf-8"}); + } catch (error) { isLoading = false; stateCode = -1; notifyListeners(); return -1; } stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received List requestsListJson = json.decode(utf8.decode(response.bodyBytes)); - List _visits = requestsListJson.map( - (request) => Visit.fromJson(request)).toList(); - if(visits == null) - visits = []; + List _visits = requestsListJson.map((request) => Visit.fromJson(request)).toList(); + if (visits == null) visits = []; visits.addAll(_visits); - if(_visits.length == pageItemNumber){ + if (_visits.length == pageItemNumber) { nextPage = true; - }else{ + } else { nextPage = false; } } @@ -97,41 +87,36 @@ class PreventiveMaintenanceVisitsProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future updateGroupOfVisits ({ + Future updateGroupOfVisits({ @required String host, @required User user, VisitsGroup group, }) async { Response response; - Map body = group.toJson(); - body["token"] = user.token ?? ""; - body["uid"] = user.id; + Map body = group.toJson(); + // body["token"] = user.token ?? ""; + // body["uid"] = user.id; //userId = 397.toString(); // testing id to view data - try{ - response = await post( - Uri.parse( - host+URLs.updatePreventiveMaintenanceVisits - ), - body: body, - ); + try { + response = await ApiManager.instance.put(URLs.updatePreventiveMaintenanceVisits, body: body); stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - group.visits.forEach((visit) { - visit.status = group.status; - visit.actualDate = group.date.toString().split(" ").first; - }); + // group.visits.forEach((visit) { + // visit.status = group.status; + // visit.actualDate = group.date.toString().split(" ").first; + // }); group.visits.clear(); notifyListeners(); } return response.statusCode; - } catch(error) { + } catch (error) { isLoading = false; stateCode = -1; notifyListeners(); return -1; } } -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/regular_visits_provider.dart b/lib/controllers/providers/api/regular_visits_provider.dart index 03737f73..25e330f7 100644 --- a/lib/controllers/providers/api/regular_visits_provider.dart +++ b/lib/controllers/providers/api/regular_visits_provider.dart @@ -1,21 +1,22 @@ import 'dart:convert'; +import 'package:flutter/cupertino.dart'; +import 'package:http/http.dart'; +import 'package:logger/logger.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/pantry/pentry.dart'; import 'package:test_sa/models/user.dart'; import 'package:test_sa/models/visits/visit.dart'; import 'package:test_sa/models/visits/visits_group.dart'; import 'package:test_sa/models/visits/visits_search.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:http/http.dart'; - -class RegularVisitsProvider extends ChangeNotifier{ +class RegularVisitsProvider extends ChangeNotifier { // number of items call in each request - final pageItemNumber = 50; + final pageItemNumber = 20; //reset provider data - void reset(){ + void reset() { visits = null; nextPage = true; stateCode = null; @@ -44,93 +45,94 @@ class RegularVisitsProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getVisits ({ + Future getVisits({ @required String host, @required User user, - // VisitsSearch visitsSearch, + // VisitsSearch visitsSearch, }) async { - if(isLoading == true) - return -2; + if (isLoading == true) return -2; isLoading = true; + if (visits == null) notifyListeners(); Response response; //userId = 397.toString(); // testing id to view data - try{ - response = await get( - Uri.parse( - host+URLs.getRegularVisits - +"?uid=${user.id}" - "&token=${user.token}" - "&page=${(visits?.length ?? 0) ~/pageItemNumber}" - +visitsSearch?.toSearchString() ?? "" - ), - headers: { - "Content-Type":"application/json; charset=utf-8" - } + + try { + Map body = {}; + body.addAll(visitsSearch.toMap()); + body["pageNumber"] = (visits?.length ?? 0) ~/ pageItemNumber + 1; + body["pageSize"] = pageItemNumber; + + response = await ApiManager.instance.post( + URLs.getRegularVisits, + body: body, ); - } catch(error) { + } catch (error) { isLoading = false; stateCode = -1; notifyListeners(); return -1; } stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - try{ - List requestsListJson = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", "")); - List _visits = requestsListJson.map( - (request) => Visit.fromJson(request) - ).toList(); - if(visits == null) - visits = []; + try { + List requestsListJson = json.decode(response.body)["data"]; + List _visits = requestsListJson.map((request) => Visit.fromJson(request)).toList(); + visits ??= []; + sortMostRecent(_visits); visits.addAll(_visits); - if(_visits.length == pageItemNumber){ + if (_visits.length == pageItemNumber) { nextPage = true; - }else{ + } else { nextPage = false; } - }catch(error){ + } catch (error) { + Logger().e(error); isLoading = false; stateCode = -1; notifyListeners(); return -1; } - } isLoading = false; notifyListeners(); return response.statusCode; } + void sortMostRecent(List visits) { + visits.sort((prev, next) => (visitsSearch.mostRecent ?? false) + ? DateTime.tryParse(next.createdOn).compareTo(DateTime.tryParse(prev.createdOn)) + : DateTime.tryParse(prev.createdOn).compareTo(DateTime.tryParse(next.createdOn))); + } + /// return -2 if request in progress /// return -1 if error happen when sending request /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future updateGroupOfVisits ({ + Future updateGroupOfVisits({ @required String host, @required User user, VisitsGroup group, }) async { Response response; - Map body = group.toJson(); - body["token"] = user.token ?? ""; - body["uid"] = user.id; - //userId = 397.toString(); // testing id to view data - try{ - response = await post( - Uri.parse(host+URLs.updateRegularVisits), - body: body, + + try { + Map body = group.toJson(); + + response = await ApiManager.instance.post( + URLs.getRegularVisits, + body: body, ); stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received reset(); notifyListeners(); } return response.statusCode; - } catch(error) { + } catch (error) { isLoading = false; stateCode = -1; notifyListeners(); @@ -138,46 +140,46 @@ class RegularVisitsProvider extends ChangeNotifier{ } } - Future getPently({String host,User user,String id}) async { + Future getPently({String host, User user, int id}) async { Response response; - response = await get( - Uri.parse("$host${URLs.getPentry}/$id"), - headers: { - "Content-Type":"application/json; charset=utf-8" - } - ); + response = await get(Uri.parse("$host${URLs.getPentry}/$id"), headers: {"Content-Type": "application/json; charset=utf-8"}); Pentry pantry; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { pantry = Pentry.fromMap(json.decode(utf8.decode(response.bodyBytes))); } return pantry; } - Future updatePentry ({ + Future updatePentry({ @required String host, @required User user, @required Pentry pentry, @required Visit visit, }) async { - try{ + try { Response response; - Map body = pentry.toMap(); - body["uid"] = user.id; - body["token"] = user.token; - response = await post( - Uri.parse(host+URLs.updatePentry + "/${visit.id}"), - body: body, - ); - if(response.statusCode >= 200 && response.statusCode < 300) { - visit.status = pentry.ppmVisitStatus; + Map body = pentry.toMap(visit.id); + body["id"] = visit.id; + body["assetId"] = visit.deviceId; + body["ppmScheduleId"] = visit.ppmScheduleId; + // body["token"] = user.token; + // body["vChecklists"]?.addAll({}); + // body["vCalibrationTools"]?.addAll({"visitId": visit.id,}); + // body["vKits"]?.add({"visitId": visit.id,}); + response = await ApiManager.instance.put(URLs.updatePentry, body: body); + + // response = await post( + // Uri.parse(host+URLs.updatePentry + "/${visit.id}"), + // body: body, + // ); + if (response.statusCode >= 200 && response.statusCode < 300) { + reset(); //visit.status = pentry.ppmVisitStatus; notifyListeners(); } return response.statusCode; - - } catch(error) { + } catch (error) { return -1; } - } -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/service_requests_provider.dart b/lib/controllers/providers/api/service_requests_provider.dart index 040ed855..ea03c7ee 100644 --- a/lib/controllers/providers/api/service_requests_provider.dart +++ b/lib/controllers/providers/api/service_requests_provider.dart @@ -1,9 +1,12 @@ import 'dart:convert'; +import 'dart:developer'; import 'package:flutter/cupertino.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; -import 'package:test_sa/controllers/http_status_manger/http_status_manger.dart'; +import 'package:test_sa/models/call_request_for_work_order_model.dart'; import 'package:test_sa/models/issue.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/service_report.dart'; @@ -11,15 +14,17 @@ import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/models/service_request/service_request_search.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/models/timer_model.dart'; -import 'package:test_sa/models/user.dart'; -class ServiceRequestsProvider extends ChangeNotifier{ +import '../../../models/service_request/search_work_order.dart'; +import '../../../models/user.dart'; +class ServiceRequestsProvider extends ChangeNotifier { // number of items call in each request - final pageItemNumber = 50; + final pageItemNumber = 10; //reset provider data - void reset(){ + void reset() { + workOrders = []; serviceRequests = null; nextPage = true; stateCode = null; @@ -35,6 +40,7 @@ class ServiceRequestsProvider extends ChangeNotifier{ // list of user requests List serviceRequests; + List workOrders = []; // when requests in-process _loading = true // done _loading = true @@ -48,55 +54,51 @@ class ServiceRequestsProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getRequests ({ - @required String host, - @required User user, - @required String hospitalId, - }) async { - if(isLoading == true) - return -2; + Future getRequests({@required int hospitalId}) async { + if (isLoading == true) return -2; isLoading = true; + if (serviceRequests == null) notifyListeners(); Response response; - try{ - response = await get( - Uri.parse( - host+URLs.getServiceRequests - +"?uid=${user.id}" - +(hospitalId == null? "" :"&client_nid=$hospitalId") - +"&token=${user.token}" - "&page=${(serviceRequests?.length ?? 0) ~/pageItemNumber}" - +search?.toSearchString() ?? "" - ), - headers: { - "Content-Type":"application/json; charset=utf-8" - } + try { + Map body = {}; + body.addAll(search.toMap()); + body["pageNumber"] = (serviceRequests?.length ?? 0) ~/ pageItemNumber + 1; + body["pageSize"] = pageItemNumber; + + response = await ApiManager.instance.post( + URLs.getServiceRequests, + body: body, ); + stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List requestsListJson = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", "")); - List _serviceRequestsPage = requestsListJson.map( - (request) => ServiceRequest.fromJson(request)).toList(); - if(serviceRequests == null) - serviceRequests = []; - serviceRequests.addAll(_serviceRequestsPage); - if(_serviceRequestsPage.length == pageItemNumber){ + List requestsListJson = json.decode(response.body)["data"]; + List serviceRequestsPage = requestsListJson.map((request) => ServiceRequest.fromJson(request)).toList(); + serviceRequests ??= []; + sortMostRecent(serviceRequestsPage); + serviceRequests.addAll(serviceRequestsPage); + if (serviceRequestsPage.length == pageItemNumber) { nextPage = true; - }else{ + } else { nextPage = false; } } isLoading = false; notifyListeners(); return response.statusCode; - - } catch(error) { + } catch (error) { isLoading = false; stateCode = -1; notifyListeners(); return -1; } + } + void sortMostRecent(List requests) { + requests.sort( + (prev, next) => (search.mostRecent ?? false) ? DateTime.tryParse(next.date).compareTo(DateTime.tryParse(prev.date)) : DateTime.tryParse(prev.date).compareTo(DateTime.tryParse(next.date)), + ); } Future getSingleServiceRequest({ @@ -106,317 +108,569 @@ class ServiceRequestsProvider extends ChangeNotifier{ @required Subtitle subtitle, }) async { String userData = ''; - if(user != null){ - userData += "&uid="+user.id; - userData += "&token="+user.token; + if (user != null) { + userData += "&uid=" + user.id; + userData += "&token=" + user.token; } Response response; - try{ - response = await get( - Uri.parse( - host+URLs.getSingleServiceRequest - +'?call_nid=$requestId' - '$userData',) - ); - }catch(error){ - throw(HttpStatusManger.getStatusMessage( - status: -1, subtitle: subtitle)); + try { + response = await get(Uri.parse( + host + + URLs.getSingleServiceRequest + + '?call_nid=$requestId' + '$userData', + )); + } catch (error) { + throw (HttpStatusManger.getStatusMessage(status: -1, subtitle: subtitle)); } // If the call to the server was successful, parse the JSON. - if (response.statusCode >= 200 && response.statusCode < 300){ + if (response.statusCode >= 200 && response.statusCode < 300) { // If the call to the server was successful, parse the JSON. List jsonList = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", "")); List _requests = jsonList.map((i) => ServiceRequest.fromJson(i)).toList(); return _requests[0]; - }else{ - throw(HttpStatusManger.getStatusMessage( - status: response.statusCode, subtitle: subtitle)); + } else { + throw (HttpStatusManger.getStatusMessage(status: response.statusCode, subtitle: subtitle)); } - } - Future createRequest ({ + Future createRequest({ @required String host, @required User user, @required ServiceRequest serviceRequest, }) async { - var body = { - "uid": user.id, - "token": user.token ?? "", - "sn_id": serviceRequest.deviceId ?? "", - "date": (DateTime.now().millisecondsSinceEpoch).toString(), - "client": user.hospital.id ?? '', - "complaint": serviceRequest.maintenanceIssue, - "image": json.encode(serviceRequest.devicePhotos), - "priority": (serviceRequest.priority?.id).toString(), - "defect_types": (serviceRequest.defectType?.id).toString(), + "id": 0, + "calNo": "", + "callCreatedBy": {"id": user.userID, "name": user.userName ?? ""}, + "assets": serviceRequest.deviceId == null ? [] : [serviceRequest.deviceId], + "requestedDate": DateTime.now().toIso8601String(), + "requestedTime": DateTime.now().toIso8601String(), + "client": user.clientId, + "callComments": serviceRequest.callComments, + if (serviceRequest.devicePhotos.isNotEmpty) "attachmentsCallRequest": serviceRequest.devicePhotos.map((e) => {"name": e}).toList(), + "priority": serviceRequest.priority.toMap(), + "defectType": serviceRequest.defectType.toMap(), + "typeofRequest": serviceRequest.type.toMap(), + "requestedThrough": serviceRequest.requestedThrough.toMap(), + "reviewComment": null, + if (serviceRequest.audio != null) "voiceNote": serviceRequest.audio, + "callSiteContactPerson": [ + { + "id": 0, + // "employeeCode": user.email, + "name": user.userName, + "telephone": user.phoneNumber, + // "job": "", + "email": user.email, + // "land": "", + "contactUserId": user.userID, + }, + ], + "noofFollowup": 0, + "status": null, + "callLastSituation": null, + "firstAction": null, + "loanAvailablity": null, + "comments": null, + "firstActionDate": null, + "visitDate": null, + "callReview": null, }; - if(serviceRequest.audio != null){ - body["audio"] = serviceRequest.audio; + if (serviceRequest.audio != null) { + body["voiceNote"] = serviceRequest.audio; } Response response; - try{ - response = await post( - Uri.parse( - host+URLs.createRequest), - body: body, - ); + try { + response = await ApiManager.instance.post(URLs.createRequest, body: body); stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { - if(serviceRequests != null) - serviceRequests.insert( - 0, - ServiceRequest.fromJson( - json.decode(utf8.decode(response.bodyBytes))[0] - ) - ); + if (response.statusCode >= 200 && response.statusCode < 300) { + if (serviceRequests != null) serviceRequests.insert(0, ServiceRequest.fromJson(json.decode(utf8.decode(response.bodyBytes))[0])); notifyListeners(); } return response.statusCode; - - } catch(error) { + } catch (error) { return -1; } - } - Future createIssueReport ({ + Future createIssueReport({ @required String host, @required User user, @required Issue issue, }) async { Response response; - Map body = issue.toMap(); + Map body = issue.toMap(); body["uid"] = user.id; body["token"] = user.token; - try{ + try { response = await post( - Uri.parse(host+URLs.createReport), + Uri.parse(host + URLs.createReport), body: body, ); stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { - - } + if (response.statusCode >= 200 && response.statusCode < 300) {} return response.statusCode; - - } catch(error) { + } catch (error) { return -1; } - } - Future updateDate ({ + Future updateDate({ @required String host, @required User user, - @required String newDate, - @required Lookup employee, @required ServiceRequest request, + DateTime date, }) async { + Map serviceRequest = await getServiceRequestById(requestId: request.id) ?? ""; + final List callSiteContacts = (serviceRequest['callSiteContactPerson'] as List); + final Map callSiteContactPerson = callSiteContacts.isEmpty ? {} : callSiteContacts[0]; + print(callSiteContactPerson); Response response; - Map body = {}; - body["uid"] = user.id; - body["token"] = user.token; - body["nid"] = request.id; - if(newDate != null) body["date"] = newDate; - if(employee != null) body["ass_emp"] = employee.id.toString(); - try{ - response = await post( - Uri.parse( - host+URLs.updateRequestDate), + var body = { + "id": request.id, + "callNo": serviceRequest['callNo'], + "callCreatedBy": serviceRequest['callCreatedBy'], + "requestedDate": request.date ?? "", + "requestedTime": request.date ?? "", + "priority": request.priority?.toMap(), + "defectType": request.defectType?.toMap(), + "typeofRequest": request.type?.toMap(), + "requestedThrough": request.requestedThrough?.toMap(), + "voiceNote": request.audio, + "assets": request.deviceId == null ? [] : [request.deviceId], + "attachmentsCallRequest": request.devicePhotos?.map((e) => {"name": e})?.toList(), + "assignedEmployee": { + "id": request.engineerId, + "name": request.engineerName, + }, + "callSiteContactPerson": [ + { + "id": callSiteContactPerson['id'] ?? 0, + "employeeCode": callSiteContactPerson['employeeCode'], + "name": callSiteContactPerson['name'] ?? user.userName, + "telephone": callSiteContactPerson['telephone'] ?? user.phoneNumber, + "job": callSiteContactPerson['job'], + "email": callSiteContactPerson['email'] ?? user.email, + "land": callSiteContactPerson['land'], + "contactUserId": user.userID, + }, + ], + "callComments": request.callComments, + "noofFollowup": 0, + "status": request.statusId == null + ? null + : { + "id": request.statusId, + "name": request.statusLabel, + "value": request.statusValue, + }, + "callLastSituation": null, + "firstAction": request.firstAction?.toMap(), + "loanAvailablity": request.loanAvailability?.toMap(), + "comments": request.reviewComment, + "firstActionDate": date?.toIso8601String(), + "visitDate": date?.toIso8601String() ?? "", + "callReview": null, + "reviewComment": null, + }; + try { + response = await ApiManager.instance.put( + URLs.updateRequestDate, body: body, ); stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { - request.engineerName = employee.label; + if (response.statusCode >= 200 && response.statusCode < 300) { + // request.engineerName = employee.name; notifyListeners(); } return response.statusCode; - - } catch(error) { + } catch (error) { return -1; } - } - Future createServiceReport ({ + Future createServiceReport({ @required String host, @required User user, @required ServiceReport report, @required ServiceRequest request, }) async { Response response; - Map body = report.toMap(); - body["uid"] = user.id; - body["token"] = user.token; - body["job_id"] = request.id; - try{ - response = await post( - Uri.parse( - host+URLs.createServiceReport), - body: body, - ); + try { + Map body = { + "id": 0, + "parentWOId": null, + "workOrderNo": "", + "workOrderYear": null, + "workOrderSequennce": null, + "callRequest": { + "id": request.id, + }, + "assetType": report.assetType?.toMap(), + "assignedEmployee": {"id": report.engineer?.id, "name": report.engineer?.name ?? ""}, + "visitDate": report.returnToService?.toIso8601String() ?? "", + // "assistantEmployees": [ + // {"id": report.engineer.id, "name": report.engineer.name}, + // ], + "supplier": null, + "vendorTicketNumber": null, + "contactPersonWorkOrders": [ + { + "id": 0, + // "employeeCode": "", + "name": user.userName, + "telephone": user.phoneNumber, + // "job": "", + "email": user.email, + // "land": "", + "contactUserId": user.userID, + } + ], + "calllastSituation": report.callLastSituation?.toMap(), + "currentSituation": null, + "repairLocation": report.repairLocation?.toMap(), + "reason": report.reason?.toMap(), + "startofWorkTime": report.timer?.startAt?.toIso8601String() ?? "", + "endofWorkTime": report.timer?.endAt?.toIso8601String() ?? "", + "workingHours": report?.workingHours, + "travelingHours": report.travelingHours, + "travelingExpenses": report.travelingExpense ?? 0, + if (report.faultDescription != null) "faultDescription": report.faultDescription.toJson(), + "sparePartsWorkOrders": report.parts + ?.map( + (p) => { + "id": p.reportPartID ?? 0, + "sparePart": {"id": p.id, "partNo": p.code, "partName": p.name}, + "qty": p.quantity + }, + ) + ?.toList(), + "reviewComment": "", + "comment": report.comment, + "attachmentsWorkOrder": request.devicePhotos?.map((e) => {"name": e})?.toList(), + "equipmentStatus": report.equipmentStatus?.toMap(), + "suppEngineerWorkOrders": null, + "engSignature": report.signatureEngineer, + "nurseSignature": report.signatureNurse, + "woParentDto": null, + }; + // body["uid"] = user.id; + // body["token"] = user.token; + response = await ApiManager.instance.post(URLs.createServiceReport, body: body); + print(response.body); + // response = await post( + // Uri.parse( + // host+URLs.createServiceReport), + // body: body, + // ); stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { reset(); notifyListeners(); } return response.statusCode; + } catch (error) { + print(error); + return -1; + } + } - } catch(error) { + Future createSubWorkOrder({ + @required SearchWorkOrder workOrder, + }) async { + Response response; + try { + Map body = workOrder.toJson(); + response = await ApiManager.instance.post(URLs.createServiceReport, body: body); + print(response.body); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + reset(); + notifyListeners(); + } + return response.statusCode; + } catch (error) { + print(error); return -1; } + } + + CallRequestForWorkOrder callRequestForWorkOrder; + + Future getCallRequestForWorkOrder({String callId}) async { + Response response; + try { + response = await ApiManager.instance.get( + URLs.getCallRequestForWorkOrder + "?callId=$callId", + ); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + Map listJson = json.decode(response.body)["data"]; + log(listJson?.toString()); + callRequestForWorkOrder = CallRequestForWorkOrder.fromJson(listJson); + } + notifyListeners(); + return callRequestForWorkOrder; + } catch (error) { + print(error); + return null; + } } - Future createDuplicatedReport ({ + Future> searchWorkOrders({@required String callId}) async { + Response response; + + try { + var body = { + "pageSize": pageItemNumber, + "pageNumber": ((workOrders?.length ?? 0) ~/ pageItemNumber) + 1, + "callId": callId, + }; + response = await ApiManager.instance.post(URLs.searchWorkOrders, body: body); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List workOrdersJson = json.decode(response.body)["data"]; + print(workOrdersJson); + workOrders = workOrdersJson.map((request) => SearchWorkOrder.fromJson(request)).toList(); + if (workOrders.length == pageItemNumber) { + nextPage = true; + } else { + nextPage = false; + } + } + return workOrders; + } catch (e) { + return []; + } + } + + Future createDuplicatedReport({ @required String host, @required User user, @required ServiceRequest request, }) async { Response response; String userData = ''; - if(user != null){ - userData += "&uid="+user.id; - userData += "&token="+user.token; + if (user != null) { + userData += "&uid=" + user.id; + userData += "&token=" + user.token; } - try{ + try { response = await get( - Uri.parse( - host+URLs.createDuplicatedReport - +"?nid=${request.id}" - +userData), + Uri.parse(host + URLs.createDuplicatedReport + "?nid=${request.id}" + userData), ); stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { reset(); notifyListeners(); } return response.statusCode; - - } catch(error) { - + } catch (error) { return -1; } - } - Future updateServiceReport ({ - @required String host, - @required User user, + Future updateServiceReport({ @required ServiceReport report, - @required ServiceRequest request, + String host, + User user, + ServiceRequest request, }) async { Response response; - Map body = report.toMap(); - body["uid"] = user.id; - body["token"] = user.token; - body["job_id"] = request.id; - body["report_id"] = request.reportID; - try{ - response = await post( - Uri.parse( - host+URLs.updateServiceReport), - body: body, - ); - stateCode = response.statusCode; + //Map body = report.toMap(request); + // body["uid"] = user.id; + // body["token"] = user.token; + // body["job_id"] = request.id; + // body["report_id"] = request.reportID; + // try { + Map body = report.toMap(request); + // body["uid"] = user.id; + // body["token"] = user.token; + response = await ApiManager.instance.put(URLs.updateServiceReport, body: body); + // response = await post( + // Uri.parse( + // host+URLs.updateServiceReport), + // body: body, + // ); + // stateCode = response.statusCode; + + if (response.statusCode >= 200 && response.statusCode < 300) { + reset(); + notifyListeners(); + } + return response.statusCode; + // } catch (error) { + // print(error); + // return -1; + // } + } - if(response.statusCode >= 200 && response.statusCode < 300) { + Future updateWorkOrderDetails({@required SearchWorkOrder workOrder}) async { + Response response; + //Map body = report.toMap(request); + // body["uid"] = user.id; + // body["token"] = user.token; + // body["job_id"] = request.id; + // body["report_id"] = request.reportID; + try { + Map body = workOrder.toJson(); + // body["uid"] = user.id; + // body["token"] = user.token; + response = await ApiManager.instance.put(URLs.updateServiceReport, body: body); + // response = await post( + // Uri.parse( + // host+URLs.updateServiceReport), + // body: body, + // ); + // stateCode = response.statusCode; + + if (response.statusCode >= 200 && response.statusCode < 300) { reset(); notifyListeners(); } return response.statusCode; - - } catch(error) { - + } catch (error) { return -1; } - } - Future updateServiceReportTimer ({ + Future updateServiceReportTimer({ @required String host, @required User user, @required TimerModel timer, @required ServiceRequest request, }) async { Response response; - Map body = {}; + Map body = {}; body["uid"] = user.id; body["token"] = user.token; body["job_id"] = request.id; body["start_time"] = (timer.startAt.millisecondsSinceEpoch / 1000).toStringAsFixed(0); - body["end_time"] = (timer.endAt.millisecondsSinceEpoch / 1000).toStringAsFixed(0); + body["end_time"] = (timer.endAt.millisecondsSinceEpoch / 1000).toStringAsFixed(0); body["working_hours"] = (timer.durationInSecond / 60 / 60).toStringAsFixed(5); body["report_id"] = request.reportID; - try{ + try { response = await post( - Uri.parse( - host+URLs.updateServiceReport), + Uri.parse(host + URLs.updateServiceReport), body: body, ); //stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // reset(); // notifyListeners(); } return response.statusCode; - - } catch(error) { - + } catch (error) { return -1; } - } Future getSingleServiceReport({ - @required String reportId, + @required int reportId, @required String host, @required User user, @required Subtitle subtitle, }) async { - String userData = ''; - if(user != null){ - userData += "&uid="+user.id; - userData += "&token="+user.token; + Response response; + try { + response = await ApiManager.instance.get( + URLs.getServiceReport + "?workOrderId=$reportId", + ); + } catch (error) { + throw (HttpStatusManger.getStatusMessage(status: -1, subtitle: subtitle)); } - Response response; - try{ + // If the call to the server was successful, parse the JSON. + if (response.statusCode >= 200 && response.statusCode < 300) { + // If the call to the server was successful, parse the JSON. + return ServiceReport.fromJson(json.decode(response.body)["data"], reportId); + } else { + throw (HttpStatusManger.getStatusMessage(status: response.statusCode, subtitle: subtitle)); + } + } - response = await get( - Uri.parse( - host+URLs.getServiceReport - +'?report_id=$reportId' - '$userData',) + Future> getServiceRequestById({@required String requestId}) async { + Response response; + try { + response = await ApiManager.instance.get( + URLs.getServiceRequestById + "?callRequestId=$requestId", ); - - }catch(error){ - throw(HttpStatusManger.getStatusMessage( - status: -1, subtitle: subtitle)); + } catch (error) { + print(error); + return {}; } // If the call to the server was successful, parse the JSON. - if (response.statusCode >= 200 && response.statusCode < 300){ + if (response.statusCode >= 200 && response.statusCode < 300) { // If the call to the server was successful, parse the JSON. - return ServiceReport.fromJson( - json.decode(utf8.decode(response.bodyBytes)),reportId); - }else{ - throw(HttpStatusManger.getStatusMessage( - status: response.statusCode, subtitle: subtitle)); + return { + "callNo": json.decode(response.body)["data"]["callNo"], + "callCreatedBy": json.decode(response.body)["data"]["callCreatedBy"], + "callSiteContactPerson": json.decode(response.body)["data"]["callSiteContactPerson"], + "firstActionDate": json.decode(response.body)["data"]["firstActionDate"], + }; + } else { + return {}; } - } - -} \ No newline at end of file + Future> searchForWorkOrders( + SearchWorkOrder search, + String callerId, + Lookup dateOperator, + String site, + ) async { + Response response; + try { + var body = { + "pageSize": pageItemNumber, + "pageNumber": ((workOrders?.length ?? 0) ~/ pageItemNumber) + 1, + if (callerId?.isNotEmpty ?? false) "callId": callerId, + if (search.assetType != null) "assetSerialNo": search.assetType?.name, + if (search.workOrderNo != null) "workOrderNo": search.workOrderNo, + if (search.id != null) "workOrderNo": search.id?.toString(), + if (search.calllastSituation != null) "callslastSituationWO": search.calllastSituation.toMap(), + if (search.assignedEmployee != null) + "assignedEmployees": [ + search.assignedEmployee.id, + ], + // "statusWO": [], + if (site?.isNotEmpty ?? false) "site": site, + if (search.visitDate != null && dateOperator != null) "visitDateSymbol": dateOperator?.toMap(), + if (search.visitDate != null && dateOperator != null) "visitDateFrom": search.visitDate, + }; + print(body); + response = await ApiManager.instance.post(URLs.searchWorkOrders, body: body); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List workOrdersJson = json.decode(response.body)["data"]; + print(workOrdersJson); + workOrders ??= []; + workOrders.addAll(workOrdersJson.map((request) => SearchWorkOrder.fromJson(request)).toList()); + if (workOrders.length == pageItemNumber) { + nextPage = true; + } else { + nextPage = false; + } + } + return workOrders; + } catch (e) { + print(e); + return []; + } + } +} diff --git a/lib/controllers/providers/api/status_drop_down/employee/employee_provider.dart b/lib/controllers/providers/api/status_drop_down/employee/assigned_to_provider.dart similarity index 75% rename from lib/controllers/providers/api/status_drop_down/employee/employee_provider.dart rename to lib/controllers/providers/api/status_drop_down/employee/assigned_to_provider.dart index 04f6d5b6..f98e16cd 100644 --- a/lib/controllers/providers/api/status_drop_down/employee/employee_provider.dart +++ b/lib/controllers/providers/api/status_drop_down/employee/assigned_to_provider.dart @@ -3,14 +3,14 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/user.dart'; -class EmployeesProvider extends ChangeNotifier{ - +class AssignedToProvider extends ChangeNotifier { //reset provider data - void reset(){ + void reset() { _items = null; _stateCode = null; } @@ -31,7 +31,7 @@ class EmployeesProvider extends ChangeNotifier{ // failed _loading = false bool _loading; bool get isLoading => _loading; - set isLoading(bool isLoading){ + set isLoading(bool isLoading) { _loading = isLoading; notifyListeners(); } @@ -41,34 +41,29 @@ class EmployeesProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getData ({String host,User user}) async { - if(_loading == true) - return -2; + Future getData({String host, User user}) async { + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - response = await get( - Uri.parse( - host + URLs.getEmployees), + try { + response = await ApiManager.instance.get( + URLs.getEmployees, ); _stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); + List categoriesListJson = json.decode(response.body)["data"]; _items = categoriesListJson.map((type) => Lookup.fromJson(type)).toList(); } _loading = false; notifyListeners(); return response.statusCode; - } catch(error) { - + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return -1; } - } - -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/status_drop_down/employee/engineers_provider.dart b/lib/controllers/providers/api/status_drop_down/employee/engineers_provider.dart new file mode 100644 index 00000000..c075faa5 --- /dev/null +++ b/lib/controllers/providers/api/status_drop_down/employee/engineers_provider.dart @@ -0,0 +1,69 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/engineer.dart'; +import 'package:test_sa/models/user.dart'; + +class EngineersProvider extends ChangeNotifier { + //reset provider data + void reset() { + _items = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int _stateCode; + int get stateCode => _stateCode; + + // contain user data + // when user not login or register _user = null + List _items; + List get items => _items; + + // when categories in-process _loading = true + // done _loading = true + // failed _loading = false + bool _loading; + bool get isLoading => _loading; + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + Future getData({String host, User user}) async { + if (_loading == true) return -2; + _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get( + URLs.getEngineers, + ); + _stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body); + _items = categoriesListJson.map((type) => Engineer.fromJson(type)).toList(); + } + _loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/controllers/providers/api/status_drop_down/gas_refill/gas_cylinder_size_provider.dart b/lib/controllers/providers/api/status_drop_down/gas_refill/gas_cylinder_size_provider.dart index b4112034..9ae44e96 100644 --- a/lib/controllers/providers/api/status_drop_down/gas_refill/gas_cylinder_size_provider.dart +++ b/lib/controllers/providers/api/status_drop_down/gas_refill/gas_cylinder_size_provider.dart @@ -3,14 +3,14 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/user.dart'; -class GasCylinderSizesProvider extends ChangeNotifier{ - +class GasCylinderSizesProvider extends ChangeNotifier { //reset provider data - void reset(){ + void reset() { _items = null; _loading = null; _stateCode = null; @@ -32,7 +32,7 @@ class GasCylinderSizesProvider extends ChangeNotifier{ // failed _loading = false bool _loading; bool get isLoading => _loading; - set isLoading(bool isLoading){ + set isLoading(bool isLoading) { _loading = isLoading; notifyListeners(); } @@ -42,32 +42,32 @@ class GasCylinderSizesProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getData ({String host,User user,}) async { - if(_loading == true) - return -2; + Future getData({ + String host, + User user, + }) async { + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - response = await get( - Uri.parse(host + URLs.getGasCylinderSize), + try { + response = await ApiManager.instance.get( + URLs.getGasCylinderSize, ); _stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); + List categoriesListJson = json.decode(response.body)["data"]; _items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList(); } _loading = false; notifyListeners(); return response.statusCode; - } catch(error) { + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return -1; } - } - -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/status_drop_down/gas_refill/gas_cylinder_type_provider.dart b/lib/controllers/providers/api/status_drop_down/gas_refill/gas_cylinder_type_provider.dart new file mode 100644 index 00000000..52e210c8 --- /dev/null +++ b/lib/controllers/providers/api/status_drop_down/gas_refill/gas_cylinder_type_provider.dart @@ -0,0 +1,73 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/user.dart'; + +class GasCylinderTypesProvider extends ChangeNotifier { + //reset provider data + void reset() { + _items = null; + _loading = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int _stateCode; + int get stateCode => _stateCode; + + // contain user data + // when user not login or register _user = null + List _items; + List get items => _items; + + // when categories in-process _loading = true + // done _loading = true + // failed _loading = false + bool _loading; + bool get isLoading => _loading; + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + Future getData({ + String host, + User user, + }) async { + if (_loading == true) return -2; + _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get( + URLs.getGasCylinderType, + ); + _stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + _items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList(); + } + _loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/controllers/providers/api/status_drop_down/gas_refill/gas_status_provider.dart b/lib/controllers/providers/api/status_drop_down/gas_refill/gas_status_provider.dart index 24b4e018..7dc22e8d 100644 --- a/lib/controllers/providers/api/status_drop_down/gas_refill/gas_status_provider.dart +++ b/lib/controllers/providers/api/status_drop_down/gas_refill/gas_status_provider.dart @@ -1,16 +1,16 @@ import 'dart:convert'; -import 'package:test_sa/controllers/api_routes/urls.dart'; -import 'package:test_sa/models/lookup.dart'; -import 'package:test_sa/models/user.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/user.dart'; -class GasStatusProvider extends ChangeNotifier{ - +class GasStatusProvider extends ChangeNotifier { //reset provider data - void reset(){ + void reset() { _items = null; _loading = null; _stateCode = null; @@ -32,7 +32,7 @@ class GasStatusProvider extends ChangeNotifier{ // failed _loading = false bool _loading; bool get isLoading => _loading; - set isLoading(bool isLoading){ + set isLoading(bool isLoading) { _loading = isLoading; notifyListeners(); } @@ -42,31 +42,32 @@ class GasStatusProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getData ({String host,User user,}) async { - if(_loading == true) return -2; + Future getData({ + String host, + User user, + }) async { + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - response = await get( - Uri.parse(host + URLs.getGasStatus), + try { + response = await ApiManager.instance.get( + URLs.getGasStatus, ); _stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); + List categoriesListJson = json.decode(response.body)["data"]; _items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList(); } _loading = false; notifyListeners(); return response.statusCode; - } catch(error) { + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return -1; } - } - -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/status_drop_down/gas_refill/gas_types_provider.dart b/lib/controllers/providers/api/status_drop_down/gas_refill/gas_types_provider.dart index f444c233..0050c4f5 100644 --- a/lib/controllers/providers/api/status_drop_down/gas_refill/gas_types_provider.dart +++ b/lib/controllers/providers/api/status_drop_down/gas_refill/gas_types_provider.dart @@ -1,16 +1,16 @@ import 'dart:convert'; -import 'package:test_sa/controllers/api_routes/urls.dart'; -import 'package:test_sa/models/lookup.dart'; -import 'package:test_sa/models/user.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/user.dart'; -class GasTypesProvider extends ChangeNotifier{ - +class GasTypesProvider extends ChangeNotifier { //reset provider data - void reset(){ + void reset() { _items = null; _loading = null; _stateCode = null; @@ -32,7 +32,7 @@ class GasTypesProvider extends ChangeNotifier{ // failed _loading = false bool _loading; bool get isLoading => _loading; - set isLoading(bool isLoading){ + set isLoading(bool isLoading) { _loading = isLoading; notifyListeners(); } @@ -42,31 +42,32 @@ class GasTypesProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getData ({String host,User user,}) async { - if(_loading == true) return -2; + Future getData({ + String host, + User user, + }) async { + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - response = await get( - Uri.parse(host + URLs.getGasTypes), + try { + response = await ApiManager.instance.get( + URLs.getGasTypes, ); _stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); + List categoriesListJson = json.decode(response.body)["data"]; _items = categoriesListJson.map((item) => Lookup.fromJson(item)).toList(); } _loading = false; notifyListeners(); return response.statusCode; - } catch(error) { + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return -1; } - } - -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/status_drop_down/pentry/pentry_status_provider.dart b/lib/controllers/providers/api/status_drop_down/pentry/pentry_status_provider.dart index 8e3168d9..26afccf5 100644 --- a/lib/controllers/providers/api/status_drop_down/pentry/pentry_status_provider.dart +++ b/lib/controllers/providers/api/status_drop_down/pentry/pentry_status_provider.dart @@ -3,14 +3,14 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/user.dart'; -class PentryStatusProvider extends ChangeNotifier{ - +class PentryStatusProvider extends ChangeNotifier { //reset provider data - void reset(){ + void reset() { _items = null; _stateCode = null; } @@ -31,7 +31,7 @@ class PentryStatusProvider extends ChangeNotifier{ // failed _loading = false bool _loading; bool get isLoading => _loading; - set isLoading(bool isLoading){ + set isLoading(bool isLoading) { _loading = isLoading; notifyListeners(); } @@ -41,35 +41,30 @@ class PentryStatusProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getData ({String host,User user}) async { - if(_loading == true) - return -2; + Future getData({String host, User user}) async { + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - response = await get( - Uri.parse( - host + URLs.getPentryStatus), + try { + response = await ApiManager.instance.get( + URLs.getPentryStatus, ); _stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List listJson = json.decode(utf8.decode(response.bodyBytes)); - _items = listJson.map((type) => Lookup.fromIntIdJson(type)).toList(); + List listJson = json.decode(response.body)["data"]; + _items = listJson.map((type) => Lookup.fromJson(type)).toList(); } _loading = false; notifyListeners(); return response.statusCode; - } catch(error) { - + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return -1; } - } - -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/status_drop_down/pentry/pentry_task_status_provider.dart b/lib/controllers/providers/api/status_drop_down/pentry/pentry_task_status_provider.dart index 03370135..b69c310a 100644 --- a/lib/controllers/providers/api/status_drop_down/pentry/pentry_task_status_provider.dart +++ b/lib/controllers/providers/api/status_drop_down/pentry/pentry_task_status_provider.dart @@ -3,14 +3,14 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/user.dart'; -class PentryTaskStatusProvider extends ChangeNotifier{ - +class PentryTaskStatusProvider extends ChangeNotifier { //reset provider data - void reset(){ + void reset() { _items = null; _stateCode = null; } @@ -31,7 +31,7 @@ class PentryTaskStatusProvider extends ChangeNotifier{ // failed _loading = false bool _loading; bool get isLoading => _loading; - set isLoading(bool isLoading){ + set isLoading(bool isLoading) { _loading = isLoading; notifyListeners(); } @@ -41,35 +41,30 @@ class PentryTaskStatusProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getData ({String host,User user}) async { - if(_loading == true) - return -2; + Future getData({String host, User user}) async { + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - response = await get( - Uri.parse( - host + URLs.getPentryTaskStatus), + try { + response = await ApiManager.instance.get( + URLs.getPentryTaskStatus, ); _stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); - _items = categoriesListJson.map((type) => Lookup.fromIntIdJson(type)).toList(); + List categoriesListJson = json.decode(response.body)["data"]; + _items = categoriesListJson.map((type) => Lookup.fromJson(type)).toList(); } _loading = false; notifyListeners(); return response.statusCode; - } catch(error) { - + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return -1; } - } - -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/status_drop_down/pentry/pentry_visit_status_provider.dart b/lib/controllers/providers/api/status_drop_down/pentry/pentry_visit_status_provider.dart index 09b52cbb..ab0f7d7c 100644 --- a/lib/controllers/providers/api/status_drop_down/pentry/pentry_visit_status_provider.dart +++ b/lib/controllers/providers/api/status_drop_down/pentry/pentry_visit_status_provider.dart @@ -3,14 +3,14 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/user.dart'; -class PentryVisitStatusProvider extends ChangeNotifier{ - +class PentryVisitStatusProvider extends ChangeNotifier { //reset provider data - void reset(){ + void reset() { _items = null; _stateCode = null; } @@ -31,7 +31,7 @@ class PentryVisitStatusProvider extends ChangeNotifier{ // failed _loading = false bool _loading; bool get isLoading => _loading; - set isLoading(bool isLoading){ + set isLoading(bool isLoading) { _loading = isLoading; notifyListeners(); } @@ -41,34 +41,30 @@ class PentryVisitStatusProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getData ({String host,User user}) async { - if(_loading == true) - return -2; + Future getData({String host, User user}) async { + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - response = await get( - Uri.parse( - host + URLs.getPentryVisitStatus), + try { + response = await ApiManager.instance.get( + URLs.getPentryVisitStatus, ); _stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List listJson = json.decode(utf8.decode(response.bodyBytes)); - _items = listJson.map((type) => Lookup.fromIntIdJson(type)).toList(); + List listJson = json.decode(response.body)["data"]; + _items = listJson.map((type) => Lookup.fromJson(type)).toList(); } _loading = false; notifyListeners(); return response.statusCode; - } catch(error) { + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return -1; } - } - -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/status_drop_down/report/service_report_assistants_employee_provider.dart b/lib/controllers/providers/api/status_drop_down/report/service_report_assistants_employee_provider.dart new file mode 100644 index 00000000..922242a9 --- /dev/null +++ b/lib/controllers/providers/api/status_drop_down/report/service_report_assistants_employee_provider.dart @@ -0,0 +1,76 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/service_request/search_work_order.dart'; + +class ServiceReportAssistantsEmployeeProvider extends ChangeNotifier { + //reset provider data + void reset() { + _assistantEmployees = null; + _loading = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int _stateCode; + int get stateCode => _stateCode; + + // contain user data + // when user not login or register _user = null + List _assistantEmployees; + List get assistantEmployees => _assistantEmployees; + + // when categories in-process _loading = true + // done _loading = true + // failed _loading = false + bool _loading; + bool get isLoading => _loading; + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + Future getAssistantEmployees() async { + if (_loading == true) return -2; + _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get( + "${URLs.getEngineers}", + ); + // response = await get( + // Uri.parse( + // URLs.getServiceReportLastCalls + // +(serviceStatus == null ? "" : "?service_status=$serviceStatus") + // ), + // ); + _stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List usersListJson = json.decode(response.body); + _assistantEmployees = []; + _assistantEmployees = usersListJson.map((type) => AssistantEmployees.fromJson(type ?? {})).toList(); + } + _loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/controllers/providers/api/status_drop_down/report/service_report_defect_types_provider.dart b/lib/controllers/providers/api/status_drop_down/report/service_report_defect_types_provider.dart index 50efd414..2c348e02 100644 --- a/lib/controllers/providers/api/status_drop_down/report/service_report_defect_types_provider.dart +++ b/lib/controllers/providers/api/status_drop_down/report/service_report_defect_types_provider.dart @@ -3,14 +3,14 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/user.dart'; -class ServiceRequestDefectTypesProvider extends ChangeNotifier{ - +class ServiceRequestDefectTypesProvider extends ChangeNotifier { //reset provider data - void reset(){ + void reset() { _items = null; _stateCode = null; } @@ -31,7 +31,7 @@ class ServiceRequestDefectTypesProvider extends ChangeNotifier{ // failed _loading = false bool _loading; bool get isLoading => _loading; - set isLoading(bool isLoading){ + set isLoading(bool isLoading) { _loading = isLoading; notifyListeners(); } @@ -41,35 +41,29 @@ class ServiceRequestDefectTypesProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getData ({String host,User user}) async { - if(_loading == true) - return -2; + Future getData({String host, User user}) async { + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - response = await get( - Uri.parse( - host + URLs.getServiceReportDefectTypes), + try { + response = await ApiManager.instance.get( + URLs.getServiceReportDefectTypes, ); - _stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List listJson = json.decode(utf8.decode(response.bodyBytes)); - _items = listJson.map((type) => Lookup.fromIntIdJson(type)).toList(); + List listJson = json.decode(response.body)["data"]; + _items = listJson.map((type) => Lookup.fromJson(type)).toList(); } _loading = false; notifyListeners(); return response.statusCode; - } catch(error) { - + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return -1; } - } - -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/status_drop_down/report/service_report_equipment_status_provider.dart b/lib/controllers/providers/api/status_drop_down/report/service_report_equipment_status_provider.dart new file mode 100644 index 00000000..1931d54c --- /dev/null +++ b/lib/controllers/providers/api/status_drop_down/report/service_report_equipment_status_provider.dart @@ -0,0 +1,72 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/user.dart'; + +class ServiceReportEquipmentStatusProvider extends ChangeNotifier { + //reset provider data + void reset() { + _status = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int _stateCode; + + int get stateCode => _stateCode; + + // contain user data + // when user not login or register _user = null + List _status; + + List get statuses => _status; + + // when categories in-process _loading = true + // done _loading = true + // failed _loading = false + bool _loading; + + bool get isLoading => _loading; + + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + Future getTypes({String host, User user}) async { + if (_loading == true) return -2; + _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get(URLs.equipmentStatus); + + _stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + _status = categoriesListJson.map((type) => Lookup.fromJson(type)).toList(); + } + _loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/controllers/providers/api/status_drop_down/report/service_report_fault_description_provider.dart b/lib/controllers/providers/api/status_drop_down/report/service_report_fault_description_provider.dart new file mode 100644 index 00000000..bc47dfb8 --- /dev/null +++ b/lib/controllers/providers/api/status_drop_down/report/service_report_fault_description_provider.dart @@ -0,0 +1,70 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/user.dart'; + +import '../../../../../models/fault_description.dart'; + +class ServiceRequestFaultDescriptionProvider extends ChangeNotifier { + //reset provider data + void reset() { + _items = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int _stateCode; + int get stateCode => _stateCode; + + // contain user data + // when user not login or register _user = null + List _items; + List get items => _items; + + // when categories in-process _loading = true + // done _loading = true + // failed _loading = false + bool _loading; + bool get isLoading => _loading; + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + Future getCallRequestForWorkOrder({String host, User user, String requestId}) async { + if (_loading == true) return -2; + _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get( + URLs.getCallRequestForWorkOrder + "?callId=$requestId", + ); + _stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List listJson = json.decode(response.body)["data"]['asset']['modelDefinition']['modelDefRelatedDefects']; + _items = listJson?.map((type) => FaultDescription.fromJson(type))?.toList() ?? []; + } + _loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart b/lib/controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart index 50de291f..7551ad57 100644 --- a/lib/controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart +++ b/lib/controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart @@ -3,14 +3,14 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/user.dart'; -class ServiceReportLastCallsProvider extends ChangeNotifier{ - +class ServiceReportLastCallsProvider extends ChangeNotifier { //reset provider data - void reset(){ + void reset() { _calls = null; _loading = null; _stateCode = null; @@ -32,7 +32,7 @@ class ServiceReportLastCallsProvider extends ChangeNotifier{ // failed _loading = false bool _loading; bool get isLoading => _loading; - set isLoading(bool isLoading){ + set isLoading(bool isLoading) { _loading = isLoading; notifyListeners(); } @@ -42,35 +42,43 @@ class ServiceReportLastCallsProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getCalls ({String host,User user,String serviceStatus}) async { - if(_loading == true) - return -2; + Future getCalls({ + String host, + User user, + int serviceStatus, + String woId, + int id, + String typeName, + }) async { + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - response = await get( - Uri.parse( - host + URLs.getServiceReportLastCalls - +(serviceStatus == null ? "" : "?service_status=$serviceStatus") - ), + try { + // todo request new api from backend to make filter work + response = await ApiManager.instance.get( + "${URLs.getServiceReportLastCalls}?parentWOId=${woId ?? id}&isAdd=true&id=${id ?? 0}&typeTransaction=$typeName", ); + // response = await get( + // Uri.parse( + // URLs.getServiceReportLastCalls + // +(serviceStatus == null ? "" : "?service_status=$serviceStatus") + // ), + // ); _stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); - _calls = categoriesListJson.map((type) => Lookup.fromIntIdJson(type)).toList(); + List categoriesListJson = json.decode(response.body)["data"]; + _calls = categoriesListJson.map((type) => Lookup.fromJson(type)).toList(); } _loading = false; notifyListeners(); return response.statusCode; - } catch(error) { + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return -1; } - } - -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/status_drop_down/report/service_report_maintenance_situation_provider.dart b/lib/controllers/providers/api/status_drop_down/report/service_report_maintenance_situation_provider.dart new file mode 100644 index 00000000..18720589 --- /dev/null +++ b/lib/controllers/providers/api/status_drop_down/report/service_report_maintenance_situation_provider.dart @@ -0,0 +1,75 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/lookup.dart'; + +class ServiceReportMaintenanceSituationProvider extends ChangeNotifier { + //reset provider data + void reset() { + _calls = null; + _loading = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int _stateCode; + int get stateCode => _stateCode; + + // contain user data + // when user not login or register _user = null + List _calls; + List get operators => _calls; + + // when categories in-process _loading = true + // done _loading = true + // failed _loading = false + bool _loading; + bool get isLoading => _loading; + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + Future getOperators(String woId) async { + if (_loading == true) return -2; + _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get( + woId == null ? "${URLs.getMaintenanceSituation}" : "${URLs.getServiceReportLastCalls}?parentWOId=$woId&isAdd=true&id=${0}&typeTransaction='Nothing'", + ); + // response = await get( + // Uri.parse( + // URLs.getServiceReportLastCalls + // +(serviceStatus == null ? "" : "?service_status=$serviceStatus") + // ), + // ); + _stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + _calls = categoriesListJson.map((type) => Lookup.fromJson(type)).toList(); + } + _loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/controllers/providers/api/status_drop_down/report/service_report_priority_provider.dart b/lib/controllers/providers/api/status_drop_down/report/service_report_priority_provider.dart index 58fc2d98..c9160a1f 100644 --- a/lib/controllers/providers/api/status_drop_down/report/service_report_priority_provider.dart +++ b/lib/controllers/providers/api/status_drop_down/report/service_report_priority_provider.dart @@ -3,14 +3,14 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/user.dart'; -class ServiceRequestPriorityProvider extends ChangeNotifier{ - +class ServiceRequestPriorityProvider extends ChangeNotifier { //reset provider data - void reset(){ + void reset() { _items = null; _stateCode = null; } @@ -31,7 +31,7 @@ class ServiceRequestPriorityProvider extends ChangeNotifier{ // failed _loading = false bool _loading; bool get isLoading => _loading; - set isLoading(bool isLoading){ + set isLoading(bool isLoading) { _loading = isLoading; notifyListeners(); } @@ -41,34 +41,30 @@ class ServiceRequestPriorityProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getData ({String host,User user}) async { - if(_loading == true) - return -2; + Future getData({String host, User user}) async { + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - response = await get( - Uri.parse( - host + URLs.getServiceReportPriority), + try { + response = await ApiManager.instance.get( + URLs.getServiceReportPriority, ); _stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List listJson = json.decode(utf8.decode(response.bodyBytes)); - _items = listJson.map((type) => Lookup.fromIntIdJson(type)).toList(); + List listJson = json.decode(response.body)["data"]; + _items = listJson.map((type) => Lookup.fromJson(type)).toList(); } _loading = false; notifyListeners(); return response.statusCode; - } catch(error) { + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return -1; } - } - -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/status_drop_down/report/service_report_reasons_provider.dart b/lib/controllers/providers/api/status_drop_down/report/service_report_reasons_provider.dart index bac49f9f..e2f686c9 100644 --- a/lib/controllers/providers/api/status_drop_down/report/service_report_reasons_provider.dart +++ b/lib/controllers/providers/api/status_drop_down/report/service_report_reasons_provider.dart @@ -3,14 +3,14 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/user.dart'; -class ServiceReportReasonsProvider extends ChangeNotifier{ - +class ServiceReportReasonsProvider extends ChangeNotifier { //reset provider data - void reset(){ + void reset() { _reasons = null; _stateCode = null; } @@ -31,7 +31,7 @@ class ServiceReportReasonsProvider extends ChangeNotifier{ // failed _loading = false bool _loading; bool get isLoading => _loading; - set isLoading(bool isLoading){ + set isLoading(bool isLoading) { _loading = isLoading; notifyListeners(); } @@ -41,33 +41,29 @@ class ServiceReportReasonsProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getTypes ({String host,User user}) async { - if(_loading == true) - return -2; + Future getTypes({String host, User user}) async { + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - response = await get( - Uri.parse( - host + URLs.getServiceReportReasons), + try { + response = await ApiManager.instance.get( + URLs.getServiceReportReasons, ); _stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); - _reasons = categoriesListJson.map((type) => Lookup.fromIntIdJson(type)).toList(); + List categoriesListJson = json.decode(response.body)["data"]; + _reasons = categoriesListJson.map((type) => Lookup.fromJson(type)).toList(); } _loading = false; notifyListeners(); return response.statusCode; - } catch(error) { + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return -1; } - } - -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/status_drop_down/report/service_report_repair_location_provider.dart b/lib/controllers/providers/api/status_drop_down/report/service_report_repair_location_provider.dart new file mode 100644 index 00000000..c357a121 --- /dev/null +++ b/lib/controllers/providers/api/status_drop_down/report/service_report_repair_location_provider.dart @@ -0,0 +1,69 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/user.dart'; + +class ServiceReportRepairLocationProvider extends ChangeNotifier { + //reset provider data + void reset() { + _reasons = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int _stateCode; + int get stateCode => _stateCode; + + // contain user data + // when user not login or register _user = null + List _reasons; + List get reasons => _reasons; + + // when categories in-process _loading = true + // done _loading = true + // failed _loading = false + bool _loading; + bool get isLoading => _loading; + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + Future getTypes({String host, User user}) async { + if (_loading == true) return -2; + _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get( + URLs.getRepairLocation, + ); + _stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + _reasons = categoriesListJson.map((type) => Lookup.fromJson(type)).toList(); + } + _loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/controllers/providers/api/status_drop_down/report/service_report_status_provider.dart b/lib/controllers/providers/api/status_drop_down/report/service_report_status_provider.dart index 89cb100f..af3c9f86 100644 --- a/lib/controllers/providers/api/status_drop_down/report/service_report_status_provider.dart +++ b/lib/controllers/providers/api/status_drop_down/report/service_report_status_provider.dart @@ -3,14 +3,14 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/user.dart'; -class ServiceReportStatusProvider extends ChangeNotifier{ - +class ServiceReportStatusProvider extends ChangeNotifier { //reset provider data - void reset(){ + void reset() { _status = null; _stateCode = null; } @@ -31,7 +31,7 @@ class ServiceReportStatusProvider extends ChangeNotifier{ // failed _loading = false bool _loading; bool get isLoading => _loading; - set isLoading(bool isLoading){ + set isLoading(bool isLoading) { _loading = isLoading; notifyListeners(); } @@ -41,34 +41,30 @@ class ServiceReportStatusProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getTypes ({String host,User user}) async { - if(_loading == true) - return -2; + Future getTypes({String host, User user}) async { + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - response = await get( - Uri.parse( - host + URLs.getServiceReportStatus), + try { + response = await ApiManager.instance.get( + URLs.getServiceReportStatus, ); + _stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); - _status = categoriesListJson.map((type) => Lookup.fromIntIdJson(type)).toList(); + List categoriesListJson = json.decode(response.body)["data"]; + _status = categoriesListJson.map((type) => Lookup.fromJson(type)).toList(); } _loading = false; notifyListeners(); return response.statusCode; - } catch(error) { - + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return -1; } - } - -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/status_drop_down/report/service_report_types_provider.dart b/lib/controllers/providers/api/status_drop_down/report/service_report_types_provider.dart index a8b07c08..ced86e89 100644 --- a/lib/controllers/providers/api/status_drop_down/report/service_report_types_provider.dart +++ b/lib/controllers/providers/api/status_drop_down/report/service_report_types_provider.dart @@ -3,14 +3,14 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/user.dart'; -class ServiceReportTypesProvider extends ChangeNotifier{ - +class ServiceReportTypesProvider extends ChangeNotifier { //reset provider data - void reset(){ + void reset() { _types = null; _stateCode = null; } @@ -31,7 +31,7 @@ class ServiceReportTypesProvider extends ChangeNotifier{ // failed _loading = false bool _loading; bool get isLoading => _loading; - set isLoading(bool isLoading){ + set isLoading(bool isLoading) { _loading = isLoading; notifyListeners(); } @@ -41,34 +41,29 @@ class ServiceReportTypesProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getTypes ({String host,User user}) async { - if(_loading == true) - return -2; + Future getTypes({String host, User user}) async { + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - - response = await get( - Uri.parse( - host + URLs.getServiceReportTypes), + try { + response = await ApiManager.instance.get( + URLs.getServiceReportTypes, ); _stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); - _types = categoriesListJson.map((type) => Lookup.fromIntIdJson(type)).toList(); + List categoriesListJson = json.decode(response.body)["data"]; + _types = categoriesListJson.map((type) => Lookup.fromJson(type)).toList(); } _loading = false; notifyListeners(); return response.statusCode; - } catch(error) { + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return -1; } - } - -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/status_drop_down/report/service_report_users_provider.dart b/lib/controllers/providers/api/status_drop_down/report/service_report_users_provider.dart new file mode 100644 index 00000000..6fcd5f80 --- /dev/null +++ b/lib/controllers/providers/api/status_drop_down/report/service_report_users_provider.dart @@ -0,0 +1,75 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/engineer.dart'; + +class ServiceReportUsersProvider extends ChangeNotifier { + //reset provider data + void reset() { + _engineers = null; + _loading = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int _stateCode; + int get stateCode => _stateCode; + + // contain user data + // when user not login or register _user = null + List _engineers; + List get engineers => _engineers; + + // when categories in-process _loading = true + // done _loading = true + // failed _loading = false + bool _loading; + bool get isLoading => _loading; + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + Future getAllUsers() async { + if (_loading == true) return -2; + _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get( + "${URLs.getAllUsers}", + ); + // response = await get( + // Uri.parse( + // URLs.getServiceReportLastCalls + // +(serviceStatus == null ? "" : "?service_status=$serviceStatus") + // ), + // ); + _stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List usersListJson = json.decode(response.body); + _engineers = usersListJson.map((type) => Engineer.fromJson(type)).toList(); + } + _loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/controllers/providers/api/status_drop_down/report/service_report_visit_date_operator_provider.dart b/lib/controllers/providers/api/status_drop_down/report/service_report_visit_date_operator_provider.dart new file mode 100644 index 00000000..dc8d7855 --- /dev/null +++ b/lib/controllers/providers/api/status_drop_down/report/service_report_visit_date_operator_provider.dart @@ -0,0 +1,75 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/lookup.dart'; + +class ServiceReportVisitOperatorProvider extends ChangeNotifier { + //reset provider data + void reset() { + _calls = null; + _loading = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int _stateCode; + int get stateCode => _stateCode; + + // contain user data + // when user not login or register _user = null + List _calls; + List get operators => _calls; + + // when categories in-process _loading = true + // done _loading = true + // failed _loading = false + bool _loading; + bool get isLoading => _loading; + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + Future getOperators() async { + if (_loading == true) return -2; + _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get( + "${URLs.getDateOperators}", + ); + // response = await get( + // Uri.parse( + // URLs.getServiceReportLastCalls + // +(serviceStatus == null ? "" : "?service_status=$serviceStatus") + // ), + // ); + _stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + _calls = categoriesListJson.map((type) => Lookup.fromJson(type)).toList(); + } + _loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/controllers/providers/api/status_drop_down/report/service_types_provider.dart b/lib/controllers/providers/api/status_drop_down/report/service_types_provider.dart index a5bcb0a5..c28e425e 100644 --- a/lib/controllers/providers/api/status_drop_down/report/service_types_provider.dart +++ b/lib/controllers/providers/api/status_drop_down/report/service_types_provider.dart @@ -3,14 +3,14 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/user.dart'; -class ServiceStatusProvider extends ChangeNotifier{ - +class ServiceStatusProvider extends ChangeNotifier { //reset provider data - void reset(){ + void reset() { _statuses = null; _stateCode = null; } @@ -31,7 +31,7 @@ class ServiceStatusProvider extends ChangeNotifier{ // failed _loading = false bool _loading; bool get isLoading => _loading; - set isLoading(bool isLoading){ + set isLoading(bool isLoading) { _loading = isLoading; notifyListeners(); } @@ -41,35 +41,29 @@ class ServiceStatusProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future getTypes ({String host,User user}) async { - if(_loading == true) - return -2; + Future getTypes({String host, User user}) async { + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - - response = await get( - Uri.parse( - host + URLs.getServiceTypes), + try { + response = await ApiManager.instance.get( + URLs.getAssetTypes, ); _stateCode = response.statusCode; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - List categoriesListJson = json.decode(utf8.decode(response.bodyBytes)); - _statuses = categoriesListJson.map((e) => Lookup.fromIntIdJson(e)).toList(); - + List categoriesListJson = json.decode(response.body)["data"]; + _statuses = categoriesListJson.map((e) => Lookup.fromJson(e)).toList(); } _loading = false; notifyListeners(); return response.statusCode; - } catch(error) { + } catch (error) { _loading = false; _stateCode = -1; notifyListeners(); return -1; } - } - -} \ No newline at end of file +} diff --git a/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_first_action_provider.dart b/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_first_action_provider.dart new file mode 100644 index 00000000..6c1beb9d --- /dev/null +++ b/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_first_action_provider.dart @@ -0,0 +1,69 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/user.dart'; + +class ServiceFirstActionProvider extends ChangeNotifier { + //reset provider data + void reset() { + _statuses = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int _stateCode; + int get stateCode => _stateCode; + + // contain user data + // when user not login or register _user = null + List _statuses; + List get items => _statuses; + + // when categories in-process _loading = true + // done _loading = true + // failed _loading = false + bool _loading; + bool get isLoading => _loading; + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + Future getData({String host, User user}) async { + if (_loading == true) return -2; + _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get( + URLs.getServiceFirstAction, + ); + _stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + _statuses = categoriesListJson.map((e) => Lookup.fromJson(e)).toList(); + } + _loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_loan_availability_provider.dart b/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_loan_availability_provider.dart new file mode 100644 index 00000000..a4f1594a --- /dev/null +++ b/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_loan_availability_provider.dart @@ -0,0 +1,69 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/user.dart'; + +class ServiceLoanAvailabilityProvider extends ChangeNotifier { + //reset provider data + void reset() { + _statuses = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int _stateCode; + int get stateCode => _stateCode; + + // contain user data + // when user not login or register _user = null + List _statuses; + List get items => _statuses; + + // when categories in-process _loading = true + // done _loading = true + // failed _loading = false + bool _loading; + bool get isLoading => _loading; + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + Future getData({String host, User user}) async { + if (_loading == true) return -2; + _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get( + URLs.getServiceLoanAvailability, + ); + _stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + _statuses = categoriesListJson.map((e) => Lookup.fromJson(e)).toList(); + } + _loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_status_provider.dart b/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_status_provider.dart new file mode 100644 index 00000000..27de1513 --- /dev/null +++ b/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_status_provider.dart @@ -0,0 +1,69 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/user.dart'; + +class ServiceRequestStatusProvider extends ChangeNotifier { + //reset provider data + void reset() { + _statuses = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int _stateCode; + int get stateCode => _stateCode; + + // contain user data + // when user not login or register _user = null + List _statuses; + List get items => _statuses; + + // when categories in-process _loading = true + // done _loading = true + // failed _loading = false + bool _loading; + bool get isLoading => _loading; + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + Future getData({String host, User user}) async { + if (_loading == true) return -2; + _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get( + URLs.getServiceRequestStatus, + ); + _stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + _statuses = categoriesListJson.map((e) => Lookup.fromJson(e)).toList(); + } + _loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_through_provider.dart b/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_through_provider.dart new file mode 100644 index 00000000..64106b31 --- /dev/null +++ b/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_through_provider.dart @@ -0,0 +1,73 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/user.dart'; + +class ServiceRequestedThroughProvider extends ChangeNotifier { + //reset provider data + void reset() { + _statuses = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int _stateCode; + int get stateCode => _stateCode; + + // contain user data + // when user not login or register _user = null + List _statuses; + List get items => _statuses; + + // when categories in-process _loading = true + // done _loading = true + // failed _loading = false + bool _loading; + bool get isLoading => _loading; + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + Future getData({String host, User user}) async { + if (_loading == true) return -2; + _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get( + URLs.getServiceRequestThrough, + ); + _stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + _statuses = categoriesListJson.map((e) => Lookup.fromJson(e)).toList(); + } + _loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return -1; + } + } + + Lookup getDefaultItem() { + return items?.firstWhere((element) => element.name.toLowerCase().contains("app")); + } +} diff --git a/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_type_provider.dart b/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_type_provider.dart new file mode 100644 index 00000000..e38d3e78 --- /dev/null +++ b/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_type_provider.dart @@ -0,0 +1,73 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/user.dart'; + +class ServiceRequestTypeProvider extends ChangeNotifier { + //reset provider data + void reset() { + _statuses = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int _stateCode; + int get stateCode => _stateCode; + + // contain user data + // when user not login or register _user = null + List _statuses; + List get items => _statuses; + + // when categories in-process _loading = true + // done _loading = true + // failed _loading = false + bool _loading; + bool get isLoading => _loading; + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + Future getData({String host, User user}) async { + if (_loading == true) return -2; + _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get( + URLs.getServiceRequestTypes, + ); + _stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + _statuses = categoriesListJson.map((e) => Lookup.fromJson(e)).toList(); + } + _loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return -1; + } + } + + Lookup getDefaultItem() { + return items?.firstWhere((element) => element.name.toLowerCase().contains("maintenance")); + } +} diff --git a/lib/controllers/providers/api/user_provider.dart b/lib/controllers/providers/api/user_provider.dart index 843746c9..5f539f05 100644 --- a/lib/controllers/providers/api/user_provider.dart +++ b/lib/controllers/providers/api/user_provider.dart @@ -1,15 +1,16 @@ import 'dart:convert'; -import 'package:test_sa/controllers/api_routes/urls.dart'; -import 'package:test_sa/models/user.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/user.dart'; -class UserProvider extends ChangeNotifier{ - +class UserProvider extends ChangeNotifier { //reset provider data - void reset(){ + void reset() { _user = null; + ApiManager.instance.user = user; _loading = false; } @@ -19,10 +20,10 @@ class UserProvider extends ChangeNotifier{ User get user => _user; set user(User user) { _user = user; + ApiManager.instance.user = user; notifyListeners(); } - // when login or register in-process _login = true // when login or register is done or not start = false bool _loading = false; @@ -38,32 +39,31 @@ class UserProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future login ({ + Future login({ @required String host, @required User user, }) async { - if(_loading == true) - return -2; + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - response = await post( - Uri.parse( - host+URLs.login), + try { + response = await ApiManager.instance.post( + URLs.login, body: await user.toLoginJson(), ); _loading = false; - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received - _user = User.fromJson(jsonDecode(utf8.decode(response.bodyBytes))[0]); - - + _user = User.fromJson(jsonDecode(response.body)); + ApiManager.instance.user = _user; + notifyListeners(); return response.statusCode; } notifyListeners(); return response.statusCode; - } catch(error) { + } catch (error) { + print(error); _loading = false; notifyListeners(); return -1; @@ -76,32 +76,31 @@ class UserProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details about state codes check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future register ({ + Future register({ @required String host, @required User user, }) async { - if(_loading == true) - return -2; + if (_loading == true) return -2; _loading = true; notifyListeners(); Response response; - try{ - response = await post( - Uri.parse( - host+URLs.register), - body: await user.toRegisterJson() + try { + response = await ApiManager.instance.post( + URLs.register, + body: await user.toLoginJson(), ); - } catch(error) { + } catch (error) { _loading = false; notifyListeners(); return -1; } _loading = false; notifyListeners(); - if(response.statusCode >= 200 && response.statusCode < 300) { + if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received _user = User.fromJson(jsonDecode(utf8.decode(response.bodyBytes))[0]); - _user.hospital = user.hospital; + _user.clientId = user.clientId; + _user.clientName = user.clientName; notifyListeners(); return response.statusCode; } @@ -114,49 +113,45 @@ class UserProvider extends ChangeNotifier{ /// return state code if request complete may be 200, 404 or 403 /// for more details about state codes check http state manager /// lib\controllers\http_status_manger\http_status_manger.dart - Future updateProfile ({ - @required String host, - @required User user, - }) async { - if(_loading == true) - return -2; - _loading = true; - notifyListeners(); - Response response; - - Map jsonObject ={}; - jsonObject["uid"] = user.id; - jsonObject["token"] = user.token; - if(user.department.id != _user.department.id) - jsonObject["department"] = user.department.id; - if(user.whatsApp != _user.whatsApp) - jsonObject["whatsapp"] = user.whatsApp; - if(user.phoneNumber != _user.phoneNumber) - jsonObject["phone"] = user.phoneNumber; - try{ - response = await post( - Uri.parse( - host+URLs.updateProfile), - body: jsonObject - ); - } catch(error) { - _loading = false; - notifyListeners(); - return -1; - } - - _loading = false; - notifyListeners(); - - if(response.statusCode >= 200 && response.statusCode < 300) { - // client's request was successfully received - _user = User.fromJson(jsonDecode(utf8.decode(response.bodyBytes))[0]); - _user.hospital = user.hospital; - _user.department = user.department; - notifyListeners(); - return response.statusCode; - } - return response.statusCode; - } - -} \ No newline at end of file + // Future updateProfile({ + // @required String host, + // @required User user, + // }) async { + // if (_loading == true) return -2; + // _loading = true; + // notifyListeners(); + // Response response; + // + // Map jsonObject = {}; + // jsonObject["uid"] = user.id; + // jsonObject["token"] = user.token; + // if (user.departmentId != _user.departmentId) jsonObject["department"] = user.departmentId; + // // if (user.whatsApp != _user.whatsApp) jsonObject["whatsapp"] = user.whatsApp; + // if (user.phoneNumber != _user.phoneNumber) jsonObject["phone"] = user.phoneNumber; + // try { + // response = response = await ApiManager.instance.post( + // URLs.login, + // body: jsonObject, + // ); + // } catch (error) { + // _loading = false; + // notifyListeners(); + // return -1; + // } + // + // _loading = false; + // notifyListeners(); + // + // if (response.statusCode >= 200 && response.statusCode < 300) { + // // client's request was successfully received + // _user = User.fromJson(jsonDecode(utf8.decode(response.bodyBytes))[0]); + // _user.clientId = user.clientId; + // _user.clientName = user.clientName; + // _user.departmentName = user.departmentName; + // _user.departmentId = user.departmentId; + // notifyListeners(); + // return response.statusCode; + // } + // return response.statusCode; + // } +} diff --git a/lib/controllers/providers/settings/app_settings.dart b/lib/controllers/providers/settings/app_settings.dart index 2d09c2a1..65824cc7 100644 --- a/lib/controllers/providers/settings/app_settings.dart +++ b/lib/controllers/providers/settings/app_settings.dart @@ -3,4 +3,4 @@ class ASettings { static final String host = "host"; static final String language = "language"; static final String speechToText = "speech_to_text"; -} \ No newline at end of file +} diff --git a/lib/controllers/providers/settings/setting_provider.dart b/lib/controllers/providers/settings/setting_provider.dart index 118b24c1..a38b20c1 100644 --- a/lib/controllers/providers/settings/setting_provider.dart +++ b/lib/controllers/providers/settings/setting_provider.dart @@ -1,15 +1,14 @@ import 'dart:async'; import 'dart:convert'; -import 'package:test_sa/controllers/api_routes/urls.dart'; -import 'package:test_sa/models/user.dart'; import 'package:flutter/foundation.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import '../settings/app_settings.dart'; - +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/user.dart'; -class SettingProvider extends ChangeNotifier{ +import '../settings/app_settings.dart'; +class SettingProvider extends ChangeNotifier { resetSettings() async { SharedPreferences prefs = await SharedPreferences.getInstance(); user = null; @@ -58,40 +57,38 @@ class SettingProvider extends ChangeNotifier{ } // call loadSharedPreferences when provider initialise - SettingProvider(){ + SettingProvider() { loadSharedPreferences(); } // get app setting Future loadSharedPreferences() async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - if(prefs.containsKey(ASettings.language)){ + if (prefs.containsKey(ASettings.language)) { _language = prefs.getString(ASettings.language); - }else{ - _language = 'en'; + } else { + _language = 'en'; } - if(prefs.containsKey(ASettings.speechToText)){ + if (prefs.containsKey(ASettings.speechToText)) { _speechToText = prefs.getString(ASettings.speechToText); - }else{ - _speechToText = 'ar'; + } else { + _speechToText = 'ar'; } - if(prefs.containsKey(ASettings.user)){ + if (prefs.containsKey(ASettings.user)) { String userJson = prefs.getString(ASettings.user); user = User.fromJson(json.decode(userJson)); } - if(prefs.containsKey(ASettings.host)){ + if (prefs.containsKey(ASettings.host)) { _host = prefs.getString(ASettings.host); - } else{ + } else { _host = URLs.host1; } isLoaded = true; notifyListeners(); } - -} \ No newline at end of file +} diff --git a/lib/controllers/validator/validator.dart b/lib/controllers/validator/validator.dart index 0eb09e9c..bb84dfca 100644 --- a/lib/controllers/validator/validator.dart +++ b/lib/controllers/validator/validator.dart @@ -1,24 +1,22 @@ -class Validator{ +class Validator { // private constructor to avoid create class object Validator._(); // check if string not empty and has value - static bool hasValue(String string){ - if (string == null || string.isEmpty) - return false; + static bool hasValue(String string) { + if (string == null || string.isEmpty) return false; return true; } // Return true if email is valid. Otherwise, return false - static bool isEmail(String email){ + static bool isEmail(String email) { RegExp exp = new RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+"); - if(exp.hasMatch(email)) - return true; + if (exp.hasMatch(email)) return true; return false; } // Return true if phone number is valid. Otherwise, return false - static bool isPhoneNumber(String phoneNumber){ + static bool isPhoneNumber(String phoneNumber) { if (phoneNumber == null || phoneNumber.isEmpty) { return false; } @@ -26,17 +24,14 @@ class Validator{ final pattern = r'^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\./0-9]*$'; final regExp = RegExp(pattern); - if (regExp.hasMatch(phoneNumber)) - return true; + if (regExp.hasMatch(phoneNumber)) return true; return false; } // Return true if password is valid. Otherwise, return false - static bool isValidPassword(String password){ - if(password == null) - return false; - if(password.length <6) - return false; + static bool isValidPassword(String password) { + if (password == null) return false; + if (password.length < 6) return false; return true; } @@ -55,4 +50,4 @@ class Validator{ } return int.tryParse(value) != null; } -} \ No newline at end of file +} diff --git a/lib/extensions/int_extensions.dart b/lib/extensions/int_extensions.dart index 5f1e672e..d4d867ad 100644 --- a/lib/extensions/int_extensions.dart +++ b/lib/extensions/int_extensions.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:test_sa/views/app_style/colors.dart'; diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index 5a8f3ce5..f88f8c08 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; extension WidgetExtensions on Widget { Widget onPress(VoidCallback onTap) => InkWell(onTap: onTap, child: this); diff --git a/lib/main.dart b/lib/main.dart index dea92839..466e0528 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -13,18 +13,31 @@ import 'package:test_sa/controllers/providers/api/hospitals_provider.dart'; import 'package:test_sa/controllers/providers/api/notifications_provider.dart'; import 'package:test_sa/controllers/providers/api/regular_visits_provider.dart'; import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; -import 'package:test_sa/controllers/providers/api/status_drop_down/employee/employee_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/employee/assigned_to_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/employee/engineers_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/gas_refill/gas_cylinder_size_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/gas_refill/gas_cylinder_type_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/gas_refill/gas_status_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/gas_refill/gas_types_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/pentry/pentry_task_status_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/pentry/pentry_visit_status_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_defect_types_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_equipment_status_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_maintenance_situation_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_priority_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_users_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_visit_date_operator_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/service_reqest/service_request_first_action_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/service_reqest/service_request_loan_availability_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/service_reqest/service_request_status_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/service_reqest/service_request_through_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/service_reqest/service_request_type_provider.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/pages/login.dart'; import 'package:test_sa/views/pages/register.dart'; import 'package:test_sa/views/pages/splash_screen.dart'; +import 'package:test_sa/views/pages/sub_workorder/create_sub_workorder_page.dart'; +import 'package:test_sa/views/pages/sub_workorder/search_sub_workorder_page.dart'; import 'package:test_sa/views/pages/user/gas_refill/request_gas_refill.dart'; import 'package:test_sa/views/pages/user/gas_refill/track_gas_refill.dart'; import 'package:test_sa/views/pages/user/land_page.dart'; @@ -42,8 +55,11 @@ import 'package:test_sa/views/widgets/equipment/single_device_picker.dart'; import 'controllers/providers/api/parts_provider.dart'; import 'controllers/providers/api/preventive_maintenance_visits_provider.dart'; import 'controllers/providers/api/status_drop_down/pentry/pentry_status_provider.dart'; +import 'controllers/providers/api/status_drop_down/report/service_report_assistants_employee_provider.dart'; +import 'controllers/providers/api/status_drop_down/report/service_report_fault_description_provider.dart'; import 'controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart'; import 'controllers/providers/api/status_drop_down/report/service_report_reasons_provider.dart'; +import 'controllers/providers/api/status_drop_down/report/service_report_repair_location_provider.dart'; import 'controllers/providers/api/status_drop_down/report/service_report_status_provider.dart'; import 'controllers/providers/api/status_drop_down/report/service_report_types_provider.dart'; import 'controllers/providers/api/status_drop_down/report/service_types_provider.dart'; @@ -57,17 +73,16 @@ void main() async { WidgetsFlutterBinding.ensureInitialized(); if (Platform.isIOS) { await Firebase.initializeApp( - options: const FirebaseOptions(apiKey: "AIzaSyACQkSleNwU1jzEKR5ho1uSfZERokwwAbc", appId: "1:973582662416:ios:bc4a8061444c6a08fbc395", messagingSenderId: "973582662416", projectId: "atoms-fb912"), + options: + const FirebaseOptions(apiKey: "AIzaSyACQkSleNwU1jzEKR5ho1uSfZERokwwAbc", appId: "1:973582662416:ios:bc4a8061444c6a08fbc395", messagingSenderId: "973582662416", projectId: "atoms-fb912"), ); } else { await Firebase.initializeApp(); } - runApp( - ChangeNotifierProvider( - create: (_) => SettingProvider(), - child: MyApp(), - ) - ); + runApp(ChangeNotifierProvider( + create: (_) => SettingProvider(), + child: MyApp(), + )); } class MyApp extends StatelessWidget { @@ -88,20 +103,34 @@ class MyApp extends StatelessWidget { ChangeNotifierProvider(create: (_) => PartsProvider()), ChangeNotifierProvider(create: (_) => ServiceReportReasonsProvider()), ChangeNotifierProvider(create: (_) => ServiceReportStatusProvider()), + ChangeNotifierProvider(create: (_) => ServiceReportEquipmentStatusProvider()), ChangeNotifierProvider(create: (_) => ServiceReportTypesProvider()), ChangeNotifierProvider(create: (_) => ServiceStatusProvider()), ChangeNotifierProvider(create: (_) => ServiceReportLastCallsProvider()), ChangeNotifierProvider(create: (_) => GasCylinderSizesProvider()), + ChangeNotifierProvider(create: (_) => GasCylinderTypesProvider()), ChangeNotifierProvider(create: (_) => GasStatusProvider()), ChangeNotifierProvider(create: (_) => GasTypesProvider()), ChangeNotifierProvider(create: (_) => GasRefillProvider()), ChangeNotifierProvider(create: (_) => DeviceTransferProvider()), - ChangeNotifierProvider(create: (_) => EmployeesProvider()), + ChangeNotifierProvider(create: (_) => AssignedToProvider()), ChangeNotifierProvider(create: (_) => PentryTaskStatusProvider()), ChangeNotifierProvider(create: (_) => PentryVisitStatusProvider()), ChangeNotifierProvider(create: (_) => PentryStatusProvider()), ChangeNotifierProvider(create: (_) => ServiceRequestPriorityProvider()), ChangeNotifierProvider(create: (_) => ServiceRequestDefectTypesProvider()), + ChangeNotifierProvider(create: (_) => ServiceRequestTypeProvider()), + ChangeNotifierProvider(create: (_) => ServiceRequestedThroughProvider()), + ChangeNotifierProvider(create: (_) => ServiceRequestStatusProvider()), + ChangeNotifierProvider(create: (_) => EngineersProvider()), + ChangeNotifierProvider(create: (_) => ServiceLoanAvailabilityProvider()), + ChangeNotifierProvider(create: (_) => ServiceFirstActionProvider()), + ChangeNotifierProvider(create: (_) => ServiceReportRepairLocationProvider()), + ChangeNotifierProvider(create: (_) => ServiceRequestFaultDescriptionProvider()), + ChangeNotifierProvider(create: (_) => ServiceReportVisitOperatorProvider()), + ChangeNotifierProvider(create: (_) => ServiceReportMaintenanceSituationProvider()), + ChangeNotifierProvider(create: (_) => ServiceReportUsersProvider()), + ChangeNotifierProvider(create: (_) => ServiceReportAssistantsEmployeeProvider()), ], child: GestureDetector( onTap: () { @@ -114,18 +143,12 @@ class MyApp extends StatelessWidget { title: 'ATOMS', debugShowCheckedModeBanner: false, theme: ThemeData( - fontFamily: "Poppins", - //canvasColor: AColors.primaryColor, - scaffoldBackgroundColor: AColors.scaffoldBackgroundColor, - primaryColor: AColors.primaryColor, - indicatorColor: AColors.primaryColor, - colorScheme: const ColorScheme.light( - primary: AColors.primaryColor, - onPrimary: Colors.white, - secondary: AColors.secondaryColor, - onSecondary: Colors.white - ) - ), + fontFamily: "Poppins", + //canvasColor: AColors.primaryColor, + scaffoldBackgroundColor: AColors.scaffoldBackgroundColor, + primaryColor: AColors.primaryColor, + indicatorColor: AColors.primaryColor, + colorScheme: const ColorScheme.light(primary: AColors.primaryColor, onPrimary: Colors.white, secondary: AColors.secondaryColor, onSecondary: Colors.white)), localizationsDelegates: const [ // ... app-specific localization delegate[s] here AppLocalization.delegate, @@ -140,31 +163,30 @@ class MyApp extends StatelessWidget { locale: Locale(_settingProvider.language ?? 'en'), initialRoute: SplashScreen.id, routes: { - SplashScreen.id: (_)=> const SplashScreen(), - LandPage.id: (_)=> const LandPage(), - Login.id: (_)=> Login(), - Register.id: (_)=> Register(), - ProfilePage.id: (_)=> ProfilePage(), - ReportIssuesPage.id: (_)=> const ReportIssuesPage(), - RequestGasRefill.id: (_)=> const RequestGasRefill(), - CreateRequestPage.id: (_)=> CreateRequestPage(), - SingleHospitalPicker.id: (_)=> SingleHospitalPicker(), - SingleDevicePicker.id: (_)=> SingleDevicePicker(), - SingleDepartmentPicker.id: (_)=> SingleDepartmentPicker(), - ServiceRequestsPage.id: (_)=> ServiceRequestsPage(), - NotificationsPage.id: (_)=> NotificationsPage(), - FutureRequestServiceDetails.id: (_)=> FutureRequestServiceDetails(), - PreventiveMaintenanceVisitsPage.id: (_)=> PreventiveMaintenanceVisitsPage(), - RegularVisitsPage.id: (_)=> RegularVisitsPage(), - TrackGasRefillPage.id: (_)=> const TrackGasRefillPage(), - RequestDeviceTransfer.id: (_)=> const RequestDeviceTransfer(), - TrackDeviceTransferPage.id: (_)=> const TrackDeviceTransferPage(), + SplashScreen.id: (_) => const SplashScreen(), + LandPage.id: (_) => const LandPage(), + Login.id: (_) => Login(), + Register.id: (_) => Register(), + ProfilePage.id: (_) => ProfilePage(), + ReportIssuesPage.id: (_) => const ReportIssuesPage(), + RequestGasRefill.id: (_) => const RequestGasRefill(), + CreateRequestPage.id: (_) => const CreateRequestPage(), + SingleHospitalPicker.id: (_) => SingleHospitalPicker(), + SingleDevicePicker.id: (_) => SingleDevicePicker(), + SingleDepartmentPicker.id: (_) => SingleDepartmentPicker(), + ServiceRequestsPage.id: (_) => ServiceRequestsPage(), + NotificationsPage.id: (_) => NotificationsPage(), + FutureRequestServiceDetails.id: (_) => FutureRequestServiceDetails(), + PreventiveMaintenanceVisitsPage.id: (_) => PreventiveMaintenanceVisitsPage(), + RegularVisitsPage.id: (_) => RegularVisitsPage(), + TrackGasRefillPage.id: (_) => const TrackGasRefillPage(), + RequestDeviceTransfer.id: (_) => const RequestDeviceTransfer(), + TrackDeviceTransferPage.id: (_) => const TrackDeviceTransferPage(), + SearchSubWorkOrderPage.id: (_) => const SearchSubWorkOrderPage(), + CreateSubWorkOrderPage.id: (_) => const CreateSubWorkOrderPage(), }, ), ), ); } } - - - diff --git a/lib/models/app_notification.dart b/lib/models/app_notification.dart index d199a07e..339e3121 100644 --- a/lib/models/app_notification.dart +++ b/lib/models/app_notification.dart @@ -1,6 +1,6 @@ import 'package:test_sa/views/pages/user/requests/future_request_service_details.dart'; -class AppNotification{ +class AppNotification { String requestId; String title; String description; @@ -15,13 +15,12 @@ class AppNotification{ this.path, }); - factory AppNotification.fromJson(Map parsedJson){ + factory AppNotification.fromJson(Map parsedJson) { return AppNotification( - requestId: parsedJson["nid"], - title: parsedJson["call_client"] ?? parsedJson["title"], - description: parsedJson["task_description"], - date: parsedJson["creation_date"], - path: FutureRequestServiceDetails.id - ); + requestId: parsedJson["nid"], + title: parsedJson["call_client"] ?? parsedJson["title"], + description: parsedJson["task_description"], + date: parsedJson["creation_date"], + path: FutureRequestServiceDetails.id); } -} \ No newline at end of file +} diff --git a/lib/models/call_request_for_work_order_model.dart b/lib/models/call_request_for_work_order_model.dart new file mode 100644 index 00000000..35b34551 --- /dev/null +++ b/lib/models/call_request_for_work_order_model.dart @@ -0,0 +1,542 @@ +import 'package:test_sa/models/lookup.dart'; + +class CallRequestForWorkOrder { + int id; + String callNo; + Asset asset; + AssignedEmployee assignedEmployee; + List callSiteContactPerson; + Status status; + Status callLastSituation; + Status defectType; + Status firstAction; + int assetType; + + CallRequestForWorkOrder( + {this.id, this.callNo, this.asset, this.assignedEmployee, this.callSiteContactPerson, this.status, this.callLastSituation, this.defectType, this.firstAction, this.assetType}); + + CallRequestForWorkOrder.fromJson(Map json) { + id = json['id']; + callNo = json['callNo']; + asset = json['asset'] != null ? new Asset.fromJson(json['asset']) : null; + assignedEmployee = json['assignedEmployee'] != null ? new AssignedEmployee.fromJson(json['assignedEmployee']) : null; + if (json['callSiteContactPerson'] != null) { + callSiteContactPerson = []; + json['callSiteContactPerson'].forEach((v) { + callSiteContactPerson.add(new CallSiteContactPerson.fromJson(v)); + }); + } + status = json['status'] != null ? new Status.fromJson(json['status']) : null; + callLastSituation = json['callLastSituation'] != null ? new Status.fromJson(json['callLastSituation']) : null; + defectType = json['defectType'] != null ? new Status.fromJson(json['defectType']) : null; + firstAction = json['firstAction'] != null ? new Status.fromJson(json['firstAction']) : null; + assetType = json['assetType']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['callNo'] = this.callNo; + if (this.asset != null) { + data['asset'] = this.asset.toJson(); + } + if (this.assignedEmployee != null) { + data['assignedEmployee'] = this.assignedEmployee.toJson(); + } + if (this.callSiteContactPerson != null) { + data['callSiteContactPerson'] = this.callSiteContactPerson.map((v) => v.toJson()).toList(); + } + if (this.status != null) { + data['status'] = this.status.toJson(); + } + if (this.callLastSituation != null) { + data['callLastSituation'] = this.callLastSituation.toJson(); + } + if (this.defectType != null) { + data['defectType'] = this.defectType.toJson(); + } + if (this.firstAction != null) { + data['firstAction'] = this.firstAction.toJson(); + } + data['assetType'] = this.assetType; + return data; + } +} + +class Asset { + int id; + String assetSerialNo; + String systemID; + String assetNumber; + ModelDefinition modelDefinition; + String supplier; + String ipAddress; + String macAddress; + String portNumber; + Lookup assetReplace; + String oldAsset; + Lookup isParent; + String parentAsset; + Lookup assetType; + Site site; + Building building; + String floor; + Department department; + String room; + String testsDay; + num purchasingPrice; + String nbv; + String currency; + String poNo; + String invoiceNumber; + String invoiceDate; + String replacementDate; + Department originDepartment; + Site originSite; + String budgetYear; + String lastPOPrice; + String commissioningStatus; + String productionDate; + String edd; + String technicalInspectionDate; + String deliveryInspectionDate; + String endUserAcceptanceDate; + String receivingCommittee; + String siteWarrantyMonths; + String extendedWarrantyMonths; + String remainderWarrantyMonths; + String eomWarrantyMonthsNo; + String warrantyValue; + String warrantyEndDate; + String warrantyContractConditions; + List technicalGuidanceBooks; + String comment; + String tagCode; + + Asset( + {this.id, + this.assetSerialNo, + this.systemID, + this.assetNumber, + this.modelDefinition, + this.supplier, + this.ipAddress, + this.macAddress, + this.portNumber, + this.assetReplace, + this.oldAsset, + this.isParent, + this.parentAsset, + this.assetType, + this.site, + this.building, + this.floor, + this.department, + this.room, + this.testsDay, + this.purchasingPrice, + this.nbv, + this.currency, + this.poNo, + this.invoiceNumber, + this.invoiceDate, + this.replacementDate, + this.originDepartment, + this.originSite, + this.budgetYear, + this.lastPOPrice, + this.commissioningStatus, + this.productionDate, + this.edd, + this.technicalInspectionDate, + this.deliveryInspectionDate, + this.endUserAcceptanceDate, + this.receivingCommittee, + this.siteWarrantyMonths, + this.extendedWarrantyMonths, + this.remainderWarrantyMonths, + this.eomWarrantyMonthsNo, + this.warrantyValue, + this.warrantyEndDate, + this.warrantyContractConditions, + this.technicalGuidanceBooks, + this.comment, + this.tagCode}); + + Asset.fromJson(Map json) { + id = json['id']; + assetSerialNo = json['assetSerialNo']; + systemID = json['systemID']; + assetNumber = json['assetNumber']; + modelDefinition = json['modelDefinition'] != null ? new ModelDefinition.fromJson(json['modelDefinition']) : null; + supplier = json['supplier']; + ipAddress = json['ipAddress']; + macAddress = json['macAddress']; + portNumber = json['portNumber']; + assetReplace = json['assetReplace'] != null ? Lookup.fromJson(json['assetReplace']) : null; + oldAsset = json['oldAsset']; + isParent = json['isParent'] != null ? Lookup.fromJson(json['isParent']) : null; + parentAsset = json['parentAsset']; + assetType = json['assetType'] != null ? Lookup.fromJson(json['assetType']) : null; + site = json['site'] != null ? new Site.fromJson(json['site']) : null; + building = json['building']; + floor = json['floor']; + department = json['department'] != null ? new Department.fromJson(json['department']) : null; + room = json['room']; + testsDay = json['testsDay']; + purchasingPrice = json['purchasingPrice']; + nbv = json['nbv']; + currency = json['currency']; + poNo = json['poNo']; + invoiceNumber = json['invoiceNumber']; + invoiceDate = json['invoiceDate']; + replacementDate = json['replacementDate']; + originDepartment = json['originDepartment'] != null ? new Department.fromJson(json['originDepartment']) : null; + originSite = json['originSite'] != null ? new Site.fromJson(json['originSite']) : null; + budgetYear = json['budgetYear']; + lastPOPrice = json['lastPOPrice']; + commissioningStatus = json['commissioningStatus']; + productionDate = json['productionDate']; + edd = json['edd']; + technicalInspectionDate = json['technicalInspectionDate']; + deliveryInspectionDate = json['deliveryInspectionDate']; + endUserAcceptanceDate = json['endUserAcceptanceDate']; + receivingCommittee = json['receivingCommittee']; + siteWarrantyMonths = json['siteWarrantyMonths']; + extendedWarrantyMonths = json['extendedWarrantyMonths']; + remainderWarrantyMonths = json['remainderWarrantyMonths']; + eomWarrantyMonthsNo = json['eomWarrantyMonthsNo']; + warrantyValue = json['warrantyValue']; + warrantyEndDate = json['warrantyEndDate']; + warrantyContractConditions = json['warrantyContractConditions']; + if (json['technicalGuidanceBooks'] != null) { + technicalGuidanceBooks = []; + json['technicalGuidanceBooks'].forEach((v) { + //technicalGuidanceBooks.add(new Null.fromJson(v)); + }); + } + comment = json['comment']; + tagCode = json['tagCode']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['assetSerialNo'] = this.assetSerialNo; + data['systemID'] = this.systemID; + data['assetNumber'] = this.assetNumber; + if (this.modelDefinition != null) { + data['modelDefinition'] = this.modelDefinition.toJson(); + } + data['supplier'] = this.supplier; + data['ipAddress'] = this.ipAddress; + data['macAddress'] = this.macAddress; + data['portNumber'] = this.portNumber; + data['assetReplace'] = this.assetReplace; + data['oldAsset'] = this.oldAsset; + data['isParent'] = this.isParent; + data['parentAsset'] = this.parentAsset; + data['assetType'] = this.assetType; + if (this.site != null) { + data['site'] = this.site.toJson(); + } + data['building'] = this.building; + data['floor'] = this.floor; + if (this.department != null) { + data['department'] = this.department.toJson(); + } + data['room'] = this.room; + data['testsDay'] = this.testsDay; + data['purchasingPrice'] = this.purchasingPrice; + data['nbv'] = this.nbv; + data['currency'] = this.currency; + data['poNo'] = this.poNo; + data['invoiceNumber'] = this.invoiceNumber; + data['invoiceDate'] = this.invoiceDate; + data['replacementDate'] = this.replacementDate; + if (this.originDepartment != null) { + data['originDepartment'] = this.originDepartment.toJson(); + } + if (this.originSite != null) { + data['originSite'] = this.originSite.toJson(); + } + data['budgetYear'] = this.budgetYear; + data['lastPOPrice'] = this.lastPOPrice; + data['commissioningStatus'] = this.commissioningStatus; + data['productionDate'] = this.productionDate; + data['edd'] = this.edd; + data['technicalInspectionDate'] = this.technicalInspectionDate; + data['deliveryInspectionDate'] = this.deliveryInspectionDate; + data['endUserAcceptanceDate'] = this.endUserAcceptanceDate; + data['receivingCommittee'] = this.receivingCommittee; + data['siteWarrantyMonths'] = this.siteWarrantyMonths; + data['extendedWarrantyMonths'] = this.extendedWarrantyMonths; + data['remainderWarrantyMonths'] = this.remainderWarrantyMonths; + data['eomWarrantyMonthsNo'] = this.eomWarrantyMonthsNo; + data['warrantyValue'] = this.warrantyValue; + data['warrantyEndDate'] = this.warrantyEndDate; + data['warrantyContractConditions'] = this.warrantyContractConditions; + if (this.technicalGuidanceBooks != null) { + data['technicalGuidanceBooks'] = this.technicalGuidanceBooks.map((v) => v.toJson()).toList(); + } + data['comment'] = this.comment; + data['tagCode'] = this.tagCode; + return data; + } +} + +class ModelDefinition { + int id; + String assetName; + String modelDefCode; + String modelName; + int manufacturerId; + String manufacturerName; + String supplierName; + String replacementDate; + int lifeSpan; + List modelDefRelatedDefects; + List suppliers; + + ModelDefinition( + {this.id, + this.assetName, + this.modelDefCode, + this.modelName, + this.manufacturerId, + this.manufacturerName, + this.supplierName, + this.replacementDate, + this.lifeSpan, + this.modelDefRelatedDefects, + this.suppliers}); + + ModelDefinition.fromJson(Map json) { + id = json['id']; + assetName = json['assetName']; + modelDefCode = json['modelDefCode']; + modelName = json['modelName']; + manufacturerId = json['manufacturerId']; + manufacturerName = json['manufacturerName']; + supplierName = json['supplierName']; + replacementDate = json['replacementDate']; + lifeSpan = json['lifeSpan']; + if (json['modelDefRelatedDefects'] != null) { + modelDefRelatedDefects = []; + json['modelDefRelatedDefects'].forEach((v) { + modelDefRelatedDefects.add(new ModelDefRelatedDefects.fromJson(v)); + }); + } + if (json['suppliers'] != null) { + suppliers = []; + json['suppliers'].forEach((v) { + // suppliers!.add(new Null.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['assetName'] = this.assetName; + data['modelDefCode'] = this.modelDefCode; + data['modelName'] = this.modelName; + data['manufacturerId'] = this.manufacturerId; + data['manufacturerName'] = this.manufacturerName; + data['supplierName'] = this.supplierName; + data['replacementDate'] = this.replacementDate; + data['lifeSpan'] = this.lifeSpan; + if (this.modelDefRelatedDefects != null) { + data['modelDefRelatedDefects'] = this.modelDefRelatedDefects.map((v) => v.toJson()).toList(); + } + if (this.suppliers != null) { + data['suppliers'] = this.suppliers.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class ModelDefRelatedDefects { + int id; + String defectName; + String workPerformed; + String estimatedTime; + + ModelDefRelatedDefects({this.id, this.defectName, this.workPerformed, this.estimatedTime}); + + ModelDefRelatedDefects.fromJson(Map json) { + id = json['id']; + defectName = json['defectName']; + workPerformed = json['workPerformed']; + estimatedTime = json['estimatedTime']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['defectName'] = this.defectName; + data['workPerformed'] = this.workPerformed; + data['estimatedTime'] = this.estimatedTime; + return data; + } +} + +class Site { + int id; + int customerCode; + String custName; + List buildings; + + Site({this.id, this.customerCode, this.custName, this.buildings}); + + Site.fromJson(Map json) { + id = json['id']; + customerCode = json['customerCode']; + custName = json['custName']; + if (json['buildings'] != null) { + buildings = []; + json['buildings'].forEach((v) { + // buildings!.add(new Null.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['customerCode'] = this.customerCode; + data['custName'] = this.custName; + if (this.buildings != null) { + data['buildings'] = this.buildings.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Department { + int id; + String departmentName; + String departmentCode; + String ntCode; + + Department({this.id, this.departmentName, this.departmentCode, this.ntCode}); + + Department.fromJson(Map json) { + id = json['id']; + departmentName = json['departmentName']; + departmentCode = json['departmentCode']; + ntCode = json['ntCode']; + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['departmentName'] = departmentName; + data['departmentCode'] = departmentCode; + data['ntCode'] = ntCode; + return data; + } +} + +class AssignedEmployee { + String id; + String name; + + AssignedEmployee({this.id, this.name}); + + AssignedEmployee.fromJson(Map json) { + id = json['id']; + name = json['name']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + return data; + } +} + +class CallSiteContactPerson { + int id; + String employeeCode; + String name; + String telephone; + String job; + String email; + String land; + String contactUserId; + + CallSiteContactPerson({this.id, this.employeeCode, this.name, this.telephone, this.job, this.email, this.land, this.contactUserId}); + + CallSiteContactPerson.fromJson(Map json) { + id = json['id']; + employeeCode = json['employeeCode']; + name = json['name']; + telephone = json['telephone']; + job = json['job']; + email = json['email']; + land = json['land']; + contactUserId = json['contactUserId']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['employeeCode'] = this.employeeCode; + data['name'] = this.name; + data['telephone'] = this.telephone; + data['job'] = this.job; + data['email'] = this.email; + data['land'] = this.land; + data['contactUserId'] = this.contactUserId; + return data; + } +} + +class Status { + int id; + String name; + int value; + + Status({this.id, this.name, this.value}); + + Status.fromJson(Map json) { + id = json['id']; + name = json['name']; + value = json['value']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + data['value'] = this.value; + return data; + } +} + +class Building { + int id; + String name; + int value; + var floor; + + Building({this.id, this.name, this.value, this.floor}); + + Building.fromJson(Map json) { + id = json['id']; + name = json['name']; + value = json['value']; + floor = json['floor']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + data['value'] = this.value; + data['floor'] = this.floor; + return data; + } +} diff --git a/lib/models/customer.dart b/lib/models/customer.dart new file mode 100644 index 00000000..5b0e1d8c --- /dev/null +++ b/lib/models/customer.dart @@ -0,0 +1,149 @@ +class Customer { + List data; + String message; + String innerMessage; + int responseCode; + bool isSuccess; + + Customer({this.data, this.message, this.innerMessage, this.responseCode, this.isSuccess}); + + Customer.fromJson(Map json) { + if (json['data'] != null) { + data = []; + json['data'].forEach((v) { + data.add(new Data.fromJson(v)); + }); + } + message = json['message']; + innerMessage = json['innerMessage']; + responseCode = json['responseCode']; + isSuccess = json['isSuccess']; + } + + Map toJson() { + final Map data = new Map(); + if (this.data != null) { + data['data'] = this.data.map((v) => v.toJson()).toList(); + } + data['message'] = this.message; + data['innerMessage'] = this.innerMessage; + data['responseCode'] = this.responseCode; + data['isSuccess'] = this.isSuccess; + return data; + } +} + +class Data { + int id; + int customerCode; + String custName; + List buildings; + + Data({this.id, this.customerCode, this.custName, this.buildings}); + + Data.fromJson(Map json) { + id = json['id']; + customerCode = json['customerCode']; + custName = json['custName']; + if (json['buildings'] != null) { + buildings = []; + json['buildings'].forEach((v) { + buildings.add(new Buildings.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['customerCode'] = this.customerCode; + data['custName'] = this.custName; + if (this.buildings != null) { + data['buildings'] = this.buildings.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Buildings { + int id; + String name; + int value; + List floors; + + Buildings({this.id, this.name, this.value, this.floors}); + + Buildings.fromJson(Map json) { + id = json['id']; + name = json['name']; + value = json['value']; + if (json['floors'] != null) { + floors = []; + json['floors'].forEach((v) { + floors.add(new Floors.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + data['value'] = this.value; + if (this.floors != null) { + data['floors'] = this.floors.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Floors { + int id; + String name; + int value; + List departments; + + Floors({this.id, this.name, this.value, this.departments}); + + Floors.fromJson(Map json) { + id = json['id']; + name = json['name']; + value = json['value']; + if (json['departments'] != null) { + departments = []; + json['departments'].forEach((v) { + departments.add(new Departments.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + data['value'] = this.value; + if (this.departments != null) { + data['departments'] = this.departments.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Departments { + int id; + String name; + + Departments({this.id, this.name}); + + Departments.fromJson(Map json) { + id = json['id']; + name = json['name']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['name'] = this.name; + return data; + } +} diff --git a/lib/models/department.dart b/lib/models/department.dart index 27df7b06..36b744a5 100644 --- a/lib/models/department.dart +++ b/lib/models/department.dart @@ -1,5 +1,5 @@ -class Department{ - String id; +class Department { + int id; String name; Department({ @@ -7,16 +7,16 @@ class Department{ this.name, }); - factory Department.fromJson(Map parsedJson){ + factory Department.fromJson(Map parsedJson) { return Department( - id: parsedJson["nid"] ?? parsedJson["id"], - name: parsedJson["dept_name"] ?? parsedJson["value"], + id: parsedJson["id"], + name: parsedJson["name"], ); } - factory Department.fromDepartment(Department department){ + factory Department.fromDepartment(Department department) { return Department( id: department?.id, name: department?.name, ); } -} \ No newline at end of file +} diff --git a/lib/models/device/device.dart b/lib/models/device/device.dart index b84b8715..c348d2f8 100644 --- a/lib/models/device/device.dart +++ b/lib/models/device/device.dart @@ -1,66 +1,90 @@ -class Device{ - String id; +import 'package:test_sa/models/hospital.dart'; +import 'package:test_sa/models/lookup.dart'; + +import 'model.dart'; + +class Device { + int id; String serialNumber; String number; - String brand; - String model; - DateTime productionDate; - DateTime supplyDate; - DateTime installDate; - DateTime receivingDate; - DateTime operationDate; - DateTime warrantyDate; + String assetName; + String destBuildingName; + int destBuildingId; + String destDepartmentName; + int destDepartmentId; + String destRoom; + String destFloor; + int destFloorId; + String destSiteName; + + // String brand; + // String model; + ModelDefinition modelDefinition; + Hospital hospital; Device({ this.id, this.serialNumber, this.number, - this.brand, - this.model, - this.productionDate, - this.supplyDate, - this.installDate, - this.receivingDate, - this.operationDate, - this.warrantyDate, + this.assetName, + this.hospital, + this.destBuildingName, + this.destDepartmentName, + this.destRoom, + this.destFloor, + this.destSiteName, + // this.brand, + // this.model, + this.modelDefinition, + this.destFloorId, + this.destDepartmentId, + this.destBuildingId, }); - factory Device.fromJson(Map parsedJson){ + factory Device.fromJson(Map parsedJson, {bool startKeyWithDest = true}) { + print("parsedJson:$parsedJson"); return Device( - id: parsedJson["nid"] ?? parsedJson["id"], - serialNumber: parsedJson["sn"] ?? parsedJson["value"], - number: parsedJson["asset_no"], - brand: parsedJson["brand"].toString(), - model: parsedJson["model"].toString(), - productionDate: getDateFromString(parsedJson["production_date"]), - supplyDate: getDateFromString(parsedJson["supply_date "]), - installDate: getDateFromString(parsedJson["install_date "]), - receivingDate: getDateFromString(parsedJson["receving_date "]), - operationDate: getDateFromString(parsedJson["operation_date "]), - warrantyDate: getDateFromString(parsedJson["warranty_date "]), - ); + id: parsedJson["id"], + serialNumber: parsedJson["assetSerialNo"], + number: parsedJson["assetNumber"], + assetName: parsedJson["assetName"], + modelDefinition: ModelDefinition.fromJson(parsedJson["modelDefinition"]), + hospital: Hospital.fromJson(parsedJson["site"]), + destBuildingName: startKeyWithDest ? parsedJson["destBuildingName"] : parsedJson['building']['name'], + destBuildingId: startKeyWithDest ? parsedJson["destBuildingName"] : parsedJson['building']['id'], + destDepartmentName: startKeyWithDest ? parsedJson["destDepartmentName"] : parsedJson['department']['departmentName'], + destDepartmentId: startKeyWithDest ? parsedJson["destDepartmentName"] : parsedJson['department']['id'], + destRoom: startKeyWithDest ? parsedJson["destRoom"] : parsedJson['room'], + destFloor: startKeyWithDest ? parsedJson["destFloor"] : parsedJson['floor']['name'], + destFloorId: startKeyWithDest ? null : parsedJson['floor']['id'], + destSiteName: parsedJson['destSiteName'] + // parsedJson["modelDefinition"] == null ? "" : + // parsedJson["modelDefinition"]["manufacturerName"], + // model: parsedJson["modelDefinition"] == null ? "" : + // parsedJson["modelDefinition"]["modelName"], + ); } - factory Device.fromDevice(Device device){ + factory Device.fromDevice(Device device) { return Device( id: device.id, serialNumber: device.serialNumber, number: device.number, - brand: device.brand, - model: device.model, - productionDate: device.productionDate, - supplyDate: device.supplyDate, - installDate: device.installDate, - receivingDate: device.receivingDate, - operationDate: device.operationDate, - warrantyDate: device.warrantyDate, + // brand: device.brand, + // model: device.model, ); } -} -DateTime getDateFromString(String unixDate){ - if(unixDate == null) - return null; - return DateTime.fromMillisecondsSinceEpoch( - int.parse(unixDate)); -} \ No newline at end of file + Map toMap(Lookup assetType) { + return { + 'id': id, + 'assetSerialNo': serialNumber, + 'assetNumber': number, + 'assetName': assetName, + 'modelDefinition': modelDefinition.toJson(), + 'site': hospital.toMap(), + 'AssetType': assetType.toMap(), + "supplier": {"id": 0, "suppliername": "string"}, + }; + } +} diff --git a/lib/models/device/device_transfer.dart b/lib/models/device/device_transfer.dart index d62913ab..50b3c593 100644 --- a/lib/models/device/device_transfer.dart +++ b/lib/models/device/device_transfer.dart @@ -1,13 +1,20 @@ +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/department.dart'; import 'package:test_sa/models/device/device.dart'; import 'package:test_sa/models/device/device_transfer_info.dart'; +import 'package:test_sa/models/hospital.dart'; +import 'package:test_sa/models/lookup.dart'; -class DeviceTransfer{ - String id; +import '../timer_model.dart'; + +class DeviceTransfer { + int id; String userId; String title; Device device; DeviceTransferInfo sender; DeviceTransferInfo receiver; + String createdOn; DeviceTransfer({ this.id, @@ -16,14 +23,15 @@ class DeviceTransfer{ this.userId, this.sender, this.receiver, + this.createdOn, }); - bool validate(){ - if(device == null) return false; + bool validate() { + if (device == null) return false; return receiver.validate(); } - fromDeviceTransfer(DeviceTransfer old){ + fromDeviceTransfer(DeviceTransfer old) { id = old.id; title = old.title; userId = old.userId; @@ -34,17 +42,76 @@ class DeviceTransfer{ final receiver = DeviceTransferInfo(); receiver.fromDetails(old.receiver); this.receiver = receiver; + createdOn = old.createdOn; } - factory DeviceTransfer.fromJson(Map parsedJson){ + factory DeviceTransfer.fromJson(Map parsedJson) { return DeviceTransfer( id: parsedJson["id"], - title: parsedJson["title"], + title: parsedJson["transferCode"], userId: parsedJson["uid"], - device: Device.fromJson(parsedJson["eq_sn"]), - sender: DeviceTransferInfo.fromJson(parsedJson,"sender_"), - receiver: DeviceTransferInfo.fromJson(parsedJson,"receiver_"), + createdOn: parsedJson['createdOn'], + device: Device( + id: parsedJson["assetId"], + number: parsedJson["assetNumber"], + assetName: parsedJson["assetName"], + serialNumber: parsedJson["assetSerialNo"], + destBuildingName: parsedJson["destBuildingName"], + destDepartmentName: parsedJson["destDepartmentName"], + destFloor: parsedJson["destFloorName"], + destRoom: parsedJson["destRoom"], + destSiteName: parsedJson["destSiteName"], + ), + sender: DeviceTransferInfo( + travelingHours: parsedJson["senderTravelingHours"], + comment: parsedJson["senderComment"], + workingHours: parsedJson["senderWorkingHours"], + timer: TimerModel( + startAt: DateTime.tryParse(parsedJson["senderStartDate"] ?? ""), + endAt: DateTime.tryParse(parsedJson["senderEndDate"] ?? ""), + durationInSecond: ((parsedJson["workingHours"] ?? 0) * 60 * 60).toInt(), + ), + // startDate: parsedJson["senderStartDate"] == null ? null : DateTime.parse(parsedJson["senderStartDate"]), + // endDate: parsedJson["senderEndDate"] == null ? null : DateTime.parse(parsedJson["senderEndDate"]), + userId: parsedJson["senderAssignedEmployeeId"], + userName: parsedJson["senderAssignedEmployeeName"], + assignedEmployeeName: parsedJson["senderAssignedEmployeeName"], + client: Hospital(id: parsedJson["senderSiteId"], name: parsedJson["senderSiteName"]), + department: Department( + id: parsedJson["senderDepartmentId"], + name: parsedJson["senderDepartmentName"], + ), + // todo add segnature + signature: URLs.getFileUrl(parsedJson["senderAttachmentName"]), + status: Lookup( + id: parsedJson["senderMachineStatusId"], + name: parsedJson["senderMachineStatusName"], + ), + ), + receiver: DeviceTransferInfo( + travelingHours: parsedJson["receiverTravelingHours"], + comment: parsedJson["receiverComment"], + workingHours: parsedJson["receiverWorkingHours"], + timer: parsedJson["receiverStartDate"] != null || parsedJson["receiverEndDate"] != null + ? TimerModel(startAt: DateTime.tryParse(parsedJson["receiverStartDate"] ?? ""), endAt: DateTime.tryParse(parsedJson["receiverEndDate"] ?? "")) + : null, + // startDate: parsedJson["receiverStartDate"] == null ? null : DateTime.parse(parsedJson["receiverStartDate"]), + // endDate: parsedJson["receiverEndDate"] == null ? null : DateTime.parse(parsedJson["receiverEndDate"]), + userId: parsedJson["receiverAssignedEmployeeId"], + userName: parsedJson["receiverAssignedEmployeeName"], + assignedEmployeeName: parsedJson["receiverAssignedEmployeeName"], + client: Hospital(id: parsedJson["destSiteId"], name: parsedJson["destSiteName"]), + department: Department( + id: parsedJson["destDepartmentId"], + name: parsedJson["destDepartmentName"], + ), + // todo add segnature + signature: URLs.getFileUrl(parsedJson["receiverAttachmentName"]), + status: Lookup( + id: parsedJson["receiverMachineStatusId"], + name: parsedJson["receiverMachineStatusName"], + ), + ), ); } } - diff --git a/lib/models/device/device_transfer_info.dart b/lib/models/device/device_transfer_info.dart index d3645b9d..dd96f298 100644 --- a/lib/models/device/device_transfer_info.dart +++ b/lib/models/device/device_transfer_info.dart @@ -2,71 +2,102 @@ import 'package:test_sa/models/department.dart'; import 'package:test_sa/models/hospital.dart'; import 'package:test_sa/models/lookup.dart'; -class DeviceTransferInfo{ +import '../timer_model.dart'; + +class DeviceTransferInfo { String userId; String comment; Hospital client; Department department; String workingHours; + + // DateTime startDate; + // DateTime endDate; String travelingHours; - String name; + String userName; String signature; + String assignedEmployeeName; Lookup status; + TimerModel timer; DeviceTransferInfo({ this.userId, this.comment, this.department, this.client, - this.name, + this.userName, this.travelingHours, + // this.startDate, + // this.endDate, this.workingHours, this.signature, this.status, + this.assignedEmployeeName, + this.timer, }); - MaptoJson(bool isSender){ - Map body = {}; + Map toJson(bool isSender) { + Map body = {}; final baseKey = isSender ? "sender_" : "receiver_"; - if(comment != null && comment.isNotEmpty) body["${baseKey}comment"] = comment; - if(workingHours != null && workingHours.isNotEmpty) body["${baseKey}working_hours"] = workingHours; - if(travelingHours != null && travelingHours.isNotEmpty) body["${baseKey}travel_hours"] = comment; - if(status != null) body["${baseKey}status"] = status.id.toString(); - if(signature != null && signature.isNotEmpty) body["${baseKey}image"] = signature; + if (comment != null && comment.isNotEmpty) body["${baseKey}comment"] = comment; + if (workingHours != null && workingHours.isNotEmpty) body["${baseKey}working_hours"] = workingHours; + // if (startDate != null) body["${baseKey}start_date"] = startDate?.toIso8601String(); + // if (endDate != null) body["${baseKey}end_date"] = endDate?.toIso8601String(); + if (timer?.startAt != null) body["${baseKey}start_date"] = timer?.startAt?.toIso8601String(); + if (timer?.endAt != null) body["${baseKey}end_date"] = timer?.endAt?.toIso8601String(); + if (travelingHours != null && travelingHours.isNotEmpty) body["${baseKey}travel_hours"] = travelingHours; + if (status != null) body["${baseKey}status"] = status.id.toString(); + if (signature != null && signature.isNotEmpty) body["${baseKey}image"] = signature; return body; } - bool validate(){ - if(client == null) return false; - if(department == null) return false; + bool validate() { + if (client == null) return false; + if (department == null) return false; return true; } - fromDetails(DeviceTransferInfo old,{bool withSignature = true}){ + fromDetails(DeviceTransferInfo old, {bool withSignature = true}) { userId = old.userId; - name = old.name; + userName = old.userName; client = Hospital.fromHospital(old.client); department = Department.fromDepartment(old.department); workingHours = old.workingHours; + // startDate = old.startDate; + // endDate = old.endDate; + timer = old.timer; travelingHours = old.travelingHours; comment = old.comment; - if(withSignature) signature = old.signature; + if (withSignature) signature = old.signature; status = old.status; } - factory DeviceTransferInfo.fromJson(Map parsedJson,String key){ + factory DeviceTransferInfo.fromJson(Map parsedJson, String key) { return DeviceTransferInfo( workingHours: parsedJson["${key}working_hours"], + // startDate: parsedJson["${key}start_date"], + // endDate: parsedJson["${key}end_date"], + timer: TimerModel( + startAt: DateTime.tryParse(parsedJson["${key}start_date"] ?? ""), + endAt: DateTime.tryParse(parsedJson["${key}end_date"] ?? ""), + durationInSecond: ((parsedJson["${key}working_hours"] ?? 0) * 60 * 60).toInt(), + ), travelingHours: parsedJson["${key}travel_hours"], - name: parsedJson["${key}name"], + userName: parsedJson["${key}name"], signature: parsedJson["${key}image"], userId: parsedJson["${key}id"], comment: parsedJson["${key}comment"], - client: Hospital.fromJson(parsedJson["${key}client"]), - department: Department.fromJson(parsedJson["${key}department"]), - status: Lookup.fromJson(parsedJson["${key}status"]), + assignedEmployeeName: parsedJson["${key}AssignedEmployeeName"], + client: Hospital(id: parsedJson["${key}SiteId"], name: parsedJson["${key}SiteName"]), + department: Department( + id: parsedJson["${key}DepartmentId"], + name: parsedJson["${key}DepartmentName"], + ), + status: Lookup( + id: parsedJson["${key}status"], + name: parsedJson["${key}status"], + ), ); } } - diff --git a/lib/models/device/device_transfer_search.dart b/lib/models/device/device_transfer_search.dart new file mode 100644 index 00000000..14cf6956 --- /dev/null +++ b/lib/models/device/device_transfer_search.dart @@ -0,0 +1,49 @@ +import '../lookup.dart'; + +class DeviceTransferSearch { + String assetName, assetNumber, site; + bool mostRecent; + Lookup dateOperator; + String from, to; + + DeviceTransferSearch({ + this.assetName, + this.assetNumber, + this.site, + this.mostRecent, + this.dateOperator, + this.from, + this.to, + }); + + Map toMap() { + Map search = {}; + if (assetName != null && assetName.isNotEmpty) { + search["assetName"] = assetName; + } + if (assetNumber != null && assetNumber.isNotEmpty) { + search["assetNumber"] = assetNumber; + } + if (site != null && site.isNotEmpty) { + search["site"] = site; + } + if (dateOperator != null && from != null) { + search["requestedDateSymbol"] = dateOperator.toMap(); + search["requestedDateFrom"] = from; + } + if (dateOperator != null && to != null) { + search["requestedDateTo"] = to; + } + return search; + } + + void fromSearch(DeviceTransferSearch newSearch) { + assetName = newSearch.assetName; + assetNumber = newSearch.assetNumber; + site = newSearch.site; + mostRecent = newSearch.mostRecent; + from = newSearch.from; + to = newSearch.to; + dateOperator = newSearch.dateOperator; + } +} diff --git a/lib/models/device/model.dart b/lib/models/device/model.dart new file mode 100644 index 00000000..25732845 --- /dev/null +++ b/lib/models/device/model.dart @@ -0,0 +1,48 @@ +class ModelDefinition { + int id; + String assetName; + String modelDefCode; + String modelName; + String manufacturerName; + String supplierName; + String replacementDate; + int lifeSpan; + + ModelDefinition({ + this.id, + this.assetName, + this.modelDefCode, + this.modelName, + this.manufacturerName, + this.supplierName, + this.replacementDate, + this.lifeSpan, + }); + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['assetName'] = assetName; + data['modelDefCode'] = modelDefCode; + data['modelName'] = modelName; + data['manufacturerName'] = manufacturerName; + data['supplierName'] = supplierName; + data['replacementDate'] = replacementDate; + data['lifeSpan'] = lifeSpan; + return data; + } + + factory ModelDefinition.fromJson(Map map) { + if (map == null) return null; + return ModelDefinition( + id: map['id'] as int, + assetName: map['assetName'] as String, + modelDefCode: map['modelDefCode'] as String, + modelName: map['modelName'] as String, + manufacturerName: map['manufacturerName'] as String, + supplierName: map['supplierName'] as String, + replacementDate: map['replacementDate'] as String, + lifeSpan: map['lifeSpan'] as int, + ); + } +} diff --git a/lib/models/engineer.dart b/lib/models/engineer.dart new file mode 100644 index 00000000..e53b0af5 --- /dev/null +++ b/lib/models/engineer.dart @@ -0,0 +1,36 @@ +class Engineer { + String id; + String name; + + Engineer({ + this.id, + this.name, + }); + + factory Engineer.fromJson(Map parsedJson) { + if (parsedJson == null) return Engineer(); + return Engineer( + id: parsedJson["userId"] ?? parsedJson["id"], + name: parsedJson["userName"] ?? parsedJson["name"], + ); + } + factory Engineer.fromEngineer(Engineer department) { + return Engineer( + id: department?.id, + name: department?.name, + ); + } + + @override + bool operator ==(Object other) => identical(this, other) || other is Engineer && id == other.id; + + @override + int get hashCode => id.hashCode; + + Map toMap() { + return { + 'id': id, + 'name': name, + }; + } +} diff --git a/lib/models/enums/user_types.dart b/lib/models/enums/user_types.dart index 2d608f7f..41df2134 100644 --- a/lib/models/enums/user_types.dart +++ b/lib/models/enums/user_types.dart @@ -1,4 +1,4 @@ -enum UsersTypes{ +enum UsersTypes { engineer, // 0 normal_user, // 1 -} \ No newline at end of file +} diff --git a/lib/models/fault_description.dart b/lib/models/fault_description.dart new file mode 100644 index 00000000..4858e55f --- /dev/null +++ b/lib/models/fault_description.dart @@ -0,0 +1,39 @@ +class FaultDescription { + FaultDescription({ + this.id, + this.defectName, + this.workPerformed, + this.estimatedTime, + }); + + FaultDescription.fromJson(dynamic json) { + id = json['id']; + defectName = json['defectName']; + workPerformed = json['workPerformed']; + estimatedTime = json['estimatedTime']; + } + num id; + String defectName; + String workPerformed; + String estimatedTime; + FaultDescription copyWith({ + num id, + String defectName, + String workPerformed, + String estimatedTime, + }) => + FaultDescription( + id: id ?? this.id, + defectName: defectName ?? this.defectName, + workPerformed: workPerformed ?? this.workPerformed, + estimatedTime: estimatedTime ?? this.estimatedTime, + ); + Map toJson() { + final map = {}; + map['id'] = id; + map['defectName'] = defectName; + map['workPerformed'] = workPerformed; + map['estimatedTime'] = estimatedTime; + return map; + } +} diff --git a/lib/models/gas_refill/gas_refill_details.dart b/lib/models/gas_refill/gas_refill_details.dart index f150e150..0c9afe0e 100644 --- a/lib/models/gas_refill/gas_refill_details.dart +++ b/lib/models/gas_refill/gas_refill_details.dart @@ -1,43 +1,46 @@ import 'package:test_sa/models/lookup.dart'; -class GasRefillDetails{ +class GasRefillDetails { Lookup type; Lookup cylinderSize; - int requestedQuantity; - int deliveredQuantity; + Lookup cylinderType; + double requestedQuantity; + double deliveredQuantity; + bool selectedForEditing; GasRefillDetails({ this.type, this.cylinderSize, + this.cylinderType, this.requestedQuantity, this.deliveredQuantity, + this.selectedForEditing, }); - bool validate(){ + bool validate() { //if(cylinderSize == null) return false; - if(type == null) return false; - if(requestedQuantity == null) return false; + if (type == null) return false; + if (requestedQuantity == null) return false; return true; } - factory GasRefillDetails.fromJson(Map parsedJson){ - return GasRefillDetails( - type: Lookup.fromJson(parsedJson["type"]), - cylinderSize: Lookup.fromJson(parsedJson["size"]), - requestedQuantity: parsedJson["requsted_qty"] == null - ? 0 : int.tryParse(parsedJson["requsted_qty"].toString()) ?? 0, - deliveredQuantity: parsedJson["deliverd_qty"] == null - ? 0 : int.tryParse(parsedJson["deliverd_qty"].toString()) ?? 0, + factory GasRefillDetails.fromJson(Map parsedJson) { + return GasRefillDetails( + type: Lookup.fromJson(parsedJson["gasType"]), + cylinderSize: Lookup.fromJson(parsedJson["cylinderSize"]), + cylinderType: Lookup.fromJson(parsedJson["cylinderType"]), + requestedQuantity: parsedJson["requestedQty"], + deliveredQuantity: parsedJson["deliverdQty"], ); } - factory GasRefillDetails.fromDetails(GasRefillDetails details){ + factory GasRefillDetails.fromDetails(GasRefillDetails details) { return GasRefillDetails( type: Lookup.fromStatus(details.type), - cylinderSize:Lookup.fromStatus(details.cylinderSize), + cylinderSize: Lookup.fromStatus(details.cylinderSize), + cylinderType: Lookup.fromStatus(details.cylinderType), requestedQuantity: details.requestedQuantity, deliveredQuantity: details.deliveredQuantity, ); } } - diff --git a/lib/models/gas_refill/gas_refill_model.dart b/lib/models/gas_refill/gas_refill_model.dart index 28773fac..aeed1b85 100644 --- a/lib/models/gas_refill/gas_refill_model.dart +++ b/lib/models/gas_refill/gas_refill_model.dart @@ -1,53 +1,107 @@ +import 'dart:typed_data'; + import 'package:test_sa/models/gas_refill/gas_refill_details.dart'; import 'package:test_sa/models/lookup.dart'; -class GasRefillModel{ - String id; - String userId; +import '../../controllers/api_routes/urls.dart'; +import '../call_request_for_work_order_model.dart'; + +class GasRefillModel { + int id; + + //String userId; String clientName; String title; Lookup status; + Lookup building; + Lookup floor; + Department department; List details; + AssignedEmployee assignedEmployee; + String signatureNurse; + String signatureEngineer; + Uint8List localNurseSignature; + Uint8List localEngineerSignature; + num workingHours; + DateTime startDate, endDate, expectedDate; GasRefillModel({ this.id, - this.userId, + //this.userId, this.clientName, this.title, this.status, this.details, + this.building, + this.floor, + this.startDate, + this.endDate, + this.expectedDate, + this.department, + this.assignedEmployee, + this.signatureNurse, + this.signatureEngineer, + this.localEngineerSignature, + this.localNurseSignature, + this.workingHours, }); - bool validate(){ - if(title == null) return false; - if(status == null) return false; - if(details == null && details.isEmpty) return false; + bool validate() { + if (title == null) return false; + if (status == null) return false; + // if (building == null) return false; + // if (floor == null) return false; + // if (department == null) return false; + // if (startDate == null) return false; + // if (endDate == null) return false; + if (details == null && details.isEmpty) return false; return true; } - fromGasRefillModel(GasRefillModel model){ + fromGasRefillModel(GasRefillModel model) { id = model.id; - userId = model.userId; + //userId = model.userId; clientName = model.clientName; title = model.title; status = Lookup.fromStatus(model.status); details = model.details.map((e) => GasRefillDetails.fromDetails(e)).toList(); + building = model.building; + floor = model.floor; + department = model.department; + startDate = model.startDate; + endDate = model.endDate; + expectedDate = model.expectedDate; + assignedEmployee = model.assignedEmployee; + localEngineerSignature = model.localEngineerSignature; + localNurseSignature = model.localNurseSignature; + signatureEngineer = model.signatureEngineer; + signatureNurse = model.signatureNurse; + workingHours = model.workingHours; } - factory GasRefillModel.fromJson(Map parsedJson){ + factory GasRefillModel.fromJson(Map parsedJson) { List details = []; - if(parsedJson["details"] != null){ - List list = parsedJson["details"]; + if (parsedJson["gazRefillDetails"] != null) { + List list = parsedJson["gazRefillDetails"]; details = list.map((e) => GasRefillDetails.fromJson(e)).toList(); } return GasRefillModel( id: parsedJson["id"], - userId: parsedJson["uid"], - title: parsedJson["title"], - clientName: parsedJson["client"], - status: Lookup.fromJson(parsedJson["status"]), + //userId: parsedJson["uid"], + title: parsedJson["gazRefillNo"], + clientName: parsedJson["site"] == null ? null : parsedJson["site"]["custName"], + status: Lookup.fromJson(parsedJson["status"] ?? {}), details: details, + building: Lookup.fromJson(parsedJson["building"] ?? {}), + floor: Lookup.fromJson(parsedJson["floor"] ?? {}), + department: Department.fromJson(parsedJson["department"] ?? {}), + startDate: DateTime.tryParse(parsedJson['startDate'] ?? ""), + endDate: DateTime.tryParse(parsedJson['endDate'] ?? ""), + expectedDate: DateTime.tryParse(parsedJson['expectedDate'] ?? ""), + assignedEmployee: AssignedEmployee.fromJson(parsedJson['assignedEmployee'] ?? {}), + signatureEngineer: URLs.getFileUrl(parsedJson["engSignature"]), + signatureNurse: URLs.getFileUrl(parsedJson["nurseSignature"]), + workingHours: parsedJson["workingHours"], ); } } - diff --git a/lib/models/hospital.dart b/lib/models/hospital.dart index 34e2e3a9..e0bf9506 100644 --- a/lib/models/hospital.dart +++ b/lib/models/hospital.dart @@ -1,23 +1,149 @@ -class Hospital{ - String id; +class Hospital { + int id; + int customerCode; String name; + List buildings; Hospital({ this.id, + this.customerCode, this.name, + this.buildings, }); - factory Hospital.fromJson(Map parsedJson){ - return Hospital( - id: parsedJson["nid"] ?? parsedJson["id"], - name: parsedJson["client_name"] ?? parsedJson["value"], - ); + factory Hospital.fromJson(Map parsedJson) { + List buildings = []; + + if (parsedJson['buildings'] != null) { + buildings = []; + parsedJson['buildings'].forEach((v) { + buildings.add(Buildings.fromJson(v)); + }); + } + + return Hospital(id: parsedJson["id"], name: parsedJson["custName"], customerCode: parsedJson["customerCode"], buildings: buildings); + } + + factory Hospital.fromHospital(Hospital hospital) { + return Hospital(id: hospital?.id, name: hospital?.name, customerCode: hospital?.customerCode, buildings: hospital?.buildings); + } + + Map toMap() { + return {'id': id, 'customerCode': customerCode, 'custName': name, "buildings": buildings}; + } +} + +// class Data { +// int id; +// int customerCode; +// String custName; +// List buildings; +// +// Data({this.id, this.customerCode, this.custName, this.buildings}); +// +// Data.fromJson(Map json) { +// id = json['id']; +// customerCode = json['customerCode']; +// custName = json['custName']; +// if (json['buildings'] != null) { +// buildings = new List(); +// json['buildings'].forEach((v) { +// buildings.add(new Buildings.fromJson(v)); +// }); +// } +// } +// +// Map toJson() { +// final Map data = new Map(); +// data['id'] = this.id; +// data['customerCode'] = this.customerCode; +// data['custName'] = this.custName; +// if (this.buildings != null) { +// data['buildings'] = this.buildings.map((v) => v.toJson()).toList(); +// } +// return data; +// } +// } + +class Buildings { + int id; + String name; + int value; + List floors; + + Buildings({this.id, this.name, this.value, this.floors}); + + Buildings.fromJson(Map json) { + id = json['id']; + name = json['name']; + value = json['value']; + if (json['floors'] != null) { + floors = []; + json['floors'].forEach((v) { + floors.add(Floors.fromJson(v)); + }); + } + } + + Map toJson({bool includeFloors = true}) { + final Map data = {}; + data['id'] = id; + data['name'] = name; + data['value'] = value; + if (floors != null && includeFloors) { + data['floors'] = floors.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Floors { + int id; + String name; + int value; + List departments; + + Floors({this.id, this.name, this.value, this.departments}); + + Floors.fromJson(Map json) { + id = json['id']; + name = json['name']; + value = json['value']; + if (json['departments'] != null) { + departments = []; + json['departments'].forEach((v) { + departments.add(Departments.fromJson(v)); + }); + } + } + + Map toJson({bool includeDepartments = true}) { + final Map data = {}; + data['id'] = id; + data['name'] = name; + data['value'] = value; + if (departments != null && includeDepartments) { + data['departments'] = departments.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Departments { + int id; + String name; + + Departments({this.id, this.name}); + + Departments.fromJson(Map json) { + id = json['id']; + name = json['name']; } - factory Hospital.fromHospital(Hospital hospital){ - return Hospital( - id: hospital?.id, - name: hospital?.name, - ); + Map toJson() { + final Map data = {}; + data['id'] = id; + data['name'] = name; + return data; } -} \ No newline at end of file +} diff --git a/lib/models/issue.dart b/lib/models/issue.dart index cc186eb6..b56acbd6 100644 --- a/lib/models/issue.dart +++ b/lib/models/issue.dart @@ -1,4 +1,4 @@ -class Issue{ +class Issue { String title; String userId; List reports; @@ -15,13 +15,13 @@ class Issue{ this.serviceRequestId, }); - Map toMap(){ - Map map ={}; - if(title != null) map["title"] = title; - if(reports != null) map["issue_report"] = reports.toString(); - if(userId != null) map["uid"] = userId; - if(description != null) map["desc"] = description; - if(serviceRequestId != null) map["call_id"] = serviceRequestId; + Map toMap() { + Map map = {}; + if (title != null) map["title"] = title; + if (reports != null) map["issue_report"] = reports.toString(); + if (userId != null) map["uid"] = userId; + if (description != null) map["desc"] = description; + if (serviceRequestId != null) map["call_id"] = serviceRequestId; return map; } -} \ No newline at end of file +} diff --git a/lib/models/lookup.dart b/lib/models/lookup.dart index 93e1f9ec..e4deb993 100644 --- a/lib/models/lookup.dart +++ b/lib/models/lookup.dart @@ -1,47 +1,58 @@ -class Lookup{ - - final String label; - final String key; +class Lookup { + //old name label + final String name; + // old name key + final int value; final int id; const Lookup({ - this.label, - this.key, + this.name, + this.value, this.id, }); @override - bool operator == (Object other) => - identical(this, other) || other is Lookup && - key == other.key && - id == other.id; - + bool operator ==(Object other) => identical(this, other) || other is Lookup && ((value != null && value == other.value) || (id != null && id == other.id)); @override - int get hashCode => id.hashCode; + int get hashCode => id?.hashCode ?? value?.hashCode; - factory Lookup.fromStatus(Lookup old){ - return Lookup( - label: old.label, - id: old.id, - key: old.key, - ); + toMap() { + return {"id": id, "name": name, "value": value}; } - factory Lookup.fromJson(Map parsedJson){ - if(parsedJson["id"] == null && parsedJson["uid"] == null) return null; + factory Lookup.fromStatus(Lookup old) { + if (old == null) return null; return Lookup( - label: parsedJson["value"], - id: parsedJson["id"] is int - ? parsedJson["id"] - : int.tryParse(parsedJson["id"] ?? parsedJson["uid"]), + name: old.name, + id: old.id, + value: old.value, ); } - factory Lookup.fromIntIdJson(Map parsedJson){ + factory Lookup.fromJson(Map parsedJson) { + if (parsedJson == null) return null; return Lookup( - label: parsedJson["value"], + name: parsedJson["name"], id: parsedJson["id"], + value: parsedJson["value"], ); } -} \ No newline at end of file + +// factory Lookup.fromJson(Map parsedJson){ +// if(parsedJson["id"] == null && parsedJson["uid"] == null) return null; +// return Lookup( +// name: parsedJson["value"], +// id: parsedJson["id"] is int +// ? parsedJson["id"] +// : int.tryParse(parsedJson["id"] ?? parsedJson["uid"]), +// ); +// } + +// factory Lookup.fromIntIdJson(Map parsedJson){ +// return Lookup( +// name: parsedJson["value"], +// id: parsedJson["id"], +// ); +// } +} diff --git a/lib/models/pantry/calibration_tools.dart b/lib/models/pantry/calibration_tools.dart index 2c70c6d2..324be41a 100644 --- a/lib/models/pantry/calibration_tools.dart +++ b/lib/models/pantry/calibration_tools.dart @@ -1,26 +1,40 @@ import 'package:test_sa/models/lookup.dart'; -class CalibrationTool{ +class CalibrationTool { + int id; Lookup assetsNumber; DateTime dataOfTesting; CalibrationTool({ + this.id, this.assetsNumber, this.dataOfTesting, }); - Map toMap() { + Map toMap(int visitId) { return { - if(assetsNumber != null) 'assetsSN': (assetsNumber?.id).toString(), - if(dataOfTesting != null) 'dataOfTesting': (dataOfTesting.millisecondsSinceEpoch ~/ 1000).toString(), + "id": id ?? 0, + "visitId": visitId, + if (assetsNumber != null) 'assetId': (assetsNumber?.id).toString(), + if (dataOfTesting != null) 'calibrationDateOfTesters': dataOfTesting.toIso8601String(), }; } factory CalibrationTool.fromMap(Map map) { return CalibrationTool( - assetsNumber: Lookup.fromJson(map['assetsSN']), - dataOfTesting: map['dataOfTesting'] == null || map['dataOfTesting'] == "" ? null : - DateTime.fromMillisecondsSinceEpoch(int.tryParse(map['dataOfTesting']) * 1000), + assetsNumber: Lookup(id: map["assetId"], name: map['assetSerialNo']), + dataOfTesting: DateTime.tryParse(map['calibrationDateOfTesters'] ?? ""), ); } -} \ No newline at end of file + + CalibrationTool copyWith({ + Lookup assetsNumber, + DateTime dataOfTesting, + }) { + return CalibrationTool( + id: id, + assetsNumber: assetsNumber ?? this.assetsNumber, + dataOfTesting: dataOfTesting ?? this.dataOfTesting, + ); + } +} diff --git a/lib/models/pantry/contact.dart b/lib/models/pantry/contact.dart index 50748bea..9f0182d4 100644 --- a/lib/models/pantry/contact.dart +++ b/lib/models/pantry/contact.dart @@ -1,6 +1,6 @@ import 'package:test_sa/models/lookup.dart'; -class Contact{ +class Contact { Lookup title; Lookup contactPerson; String job; @@ -8,14 +8,7 @@ class Contact{ String telephone; String landLine; - Contact({ - this.title, - this.contactPerson, - this.job, - this.email, - this.telephone, - this.landLine - }); + Contact({this.title, this.contactPerson, this.job, this.email, this.telephone, this.landLine}); Map toMap() { return { @@ -38,4 +31,4 @@ class Contact{ landLine: map['landLine'] as String, ); } -} \ No newline at end of file +} diff --git a/lib/models/pantry/lookups/contact_person.dart b/lib/models/pantry/lookups/contact_person.dart index 5231712c..af74b99b 100644 --- a/lib/models/pantry/lookups/contact_person.dart +++ b/lib/models/pantry/lookups/contact_person.dart @@ -1,15 +1,12 @@ import 'package:test_sa/models/lookup.dart'; class ContactTitle extends Lookup { - ContactTitle({ - int id, - String label - }):super(id: id,label: label); + ContactTitle({int id, String label}) : super(id: id, name: label); - factory ContactTitle.fromMap(Map parsedJson){ + factory ContactTitle.fromMap(Map parsedJson) { return ContactTitle( label: parsedJson["value"], id: parsedJson["id"], ); } -} \ No newline at end of file +} diff --git a/lib/models/pantry/lookups/contact_title.dart b/lib/models/pantry/lookups/contact_title.dart index 5231712c..af74b99b 100644 --- a/lib/models/pantry/lookups/contact_title.dart +++ b/lib/models/pantry/lookups/contact_title.dart @@ -1,15 +1,12 @@ import 'package:test_sa/models/lookup.dart'; class ContactTitle extends Lookup { - ContactTitle({ - int id, - String label - }):super(id: id,label: label); + ContactTitle({int id, String label}) : super(id: id, name: label); - factory ContactTitle.fromMap(Map parsedJson){ + factory ContactTitle.fromMap(Map parsedJson) { return ContactTitle( label: parsedJson["value"], id: parsedJson["id"], ); } -} \ No newline at end of file +} diff --git a/lib/models/pantry/pentry.dart b/lib/models/pantry/pentry.dart index ebd855dc..45b750da 100644 --- a/lib/models/pantry/pentry.dart +++ b/lib/models/pantry/pentry.dart @@ -1,60 +1,97 @@ import 'dart:convert'; import 'dart:io'; +import 'dart:typed_data'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/pantry/calibration_tools.dart'; import 'package:test_sa/models/pantry/pm_kit.dart'; import 'package:test_sa/models/pantry/ppm_check_list.dart'; import 'package:test_sa/models/timer_model.dart'; -class Pentry{ +class Pentry { Lookup ppmVisitStatus; Lookup status; TimerModel timer; DateTime actualVisitDate; + DateTime expectedVisitDate; String travelingHours; String image; File imageFile; + // List contacts; List ppmCheckLists; List calibrationTools; List pmKits; + String signatureNurse; + String signatureEngineer; + Uint8List localNurseSignature; + Uint8List localEngineerSignature; - Pentry({ - this.travelingHours, - this.timer, - this.status, - this.ppmVisitStatus, - this.actualVisitDate, - this.image, - this.imageFile, - // this.contacts, - this.ppmCheckLists, - this.calibrationTools, - this.pmKits, - }); + Pentry( + {this.travelingHours, + this.timer, + this.status, + this.ppmVisitStatus, + this.actualVisitDate, + this.expectedVisitDate, + this.image, + this.imageFile, + // this.contacts, + this.ppmCheckLists, + this.calibrationTools, + this.pmKits, + this.signatureNurse, + this.signatureEngineer, + this.localNurseSignature, + this.localEngineerSignature}); - bool validate(){ - if(actualVisitDate == null) return false; - if(timer == null && timer.endAt != null) return false; - if(ppmVisitStatus == null) return false; - //if(status == null) return false; + Future validate() async { + if (actualVisitDate == null) { + await Fluttertoast.showToast(msg: "Actual visit date is Required"); + return false; + } + if (expectedVisitDate == null) { + await Fluttertoast.showToast(msg: "expected visit date is Required"); + return false; + } + if (timer?.startAt == null) { + await Fluttertoast.showToast(msg: "Working Hours Required"); + return false; + } + if (timer?.endAt == null) { + await Fluttertoast.showToast(msg: "Please Stop The Timer"); + return false; + } + if (ppmVisitStatus == null) return false; + if (status?.id == null) { + await Fluttertoast.showToast(msg: "Device Status is Required"); + return false; + } return true; } - Map toMap() { - Map map = {}; - map["visit_status"] = ppmVisitStatus?.id.toString(); - if(status != null) map["pentry_status"] = status?.id.toString(); - if(travelingHours != null) map["traveling_hours"] = travelingHours; - if(imageFile != null) map["file_attachement"] = base64Encode(imageFile.readAsBytesSync()); - map["actual_date"] = (actualVisitDate.millisecondsSinceEpoch / 1000).toStringAsFixed(0); - if(timer != null){ - map["start_date"] = (timer.startAt.millisecondsSinceEpoch / 1000).toStringAsFixed(0); - map["end_date"] = ((timer.endAt ?? DateTime.now()).millisecondsSinceEpoch / 1000).toStringAsFixed(0); - map["working_hours"] = (timer.durationInSecond / 60 / 60).toStringAsFixed(5); + Map toMap(int visitId) { + Map map = {}; + map["visitStatusId"] = ppmVisitStatus?.id.toString(); + if (status != null) map["deviceStatusId"] = status?.id.toString(); + if (travelingHours != null) map["travelingHours"] = travelingHours; + //if(imageFile != null) map["file_attachement"] = base64Encode(imageFile.readAsBytesSync()); + map["actualDate"] = actualVisitDate.toIso8601String(); + map["expectedDate"] = expectedVisitDate.toIso8601String(); + if (timer != null) { + map["startDate"] = timer.startAt.toIso8601String(); + map["endDate"] = timer.endAt?.toIso8601String() ?? DateTime.now().toIso8601String(); + map["workingHours"] = (timer.durationInSecond / 60 / 60).toStringAsFixed(5); } + if (imageFile != null) { + map["vAttachments"] = [ + {"attachmentName": (imageFile.path.split("/").last + base64Encode(imageFile.readAsBytesSync()))} + ]; + } + map["travelingHours"] = travelingHours; // if(contacts?.isNotEmpty == true) { // for(int i = 0;i e.toMap()).toList()); - map["calibrationTools"] = jsonEncode(calibrationTools.map((e) => e.toMap()).toList()); - map["pmKits"] = jsonEncode(pmKits.map((e) => e.toMap()).toList()); + map["vChecklists"] = ppmCheckLists.map((e) => e.toMap(visitId)).toList(); + map["vCalibrationTools"] = calibrationTools.map((e) => e.toMap(visitId)).toList(); + map["vKits"] = pmKits.map((e) => e.toMap(visitId)).toList(); + map["nurseSignature"] = signatureNurse; //"${DateTime.now().toIso8601String()}.png|$signatureNurse"; + map["engSignature"] = signatureEngineer; //"${DateTime.now().toIso8601String()}.png|$signatureEngineer"; return map; } @@ -77,44 +116,67 @@ class Pentry{ // } List pmKits = []; - if(map['pmKits'] != null){ - pmKits =(map['pmKits'] as List) - .map((e) => PMKit.fromMap(e as Map)) - .toList(); + if (map['vKits'] != null) { + pmKits = (map['vKits'] as List).map((e) => PMKit.fromMap(e as Map)).toList(); } List ppmCheckLists = []; - if(map['ppmCheckLists'] != null){ - ppmCheckLists =(map['ppmCheckLists'] as List) - .map((e) => PPMCheckList.fromMap(e as Map)) - .toList(); + if (map['vChecklists'] != null) { + ppmCheckLists = (map['vChecklists'] as List).map((e) => PPMCheckList.fromMap(e as Map)).toList(); } List calibrationTools = []; - if(map['calibrationTools'] != null){ - calibrationTools =(map['calibrationTools'] as List) - .map((e) => CalibrationTool.fromMap(e as Map)) - .toList(); + if (map['vCalibrationTools'] != null) { + calibrationTools = (map['vCalibrationTools'] as List).map((e) => CalibrationTool.fromMap(e as Map)).toList(); } return Pentry( - status: Lookup.fromJson(map["pentry_status"]), - ppmVisitStatus: Lookup.fromJson(map["visit_status"]), - actualVisitDate: getDate(map["actual_date"]), - travelingHours: map["traveling_hours"], + status: Lookup(id: map["taskStatusId"], name: map["taskStatusName"]), + ppmVisitStatus: Lookup(id: map["visitStatusId"], name: map["visitStatusName"]), + actualVisitDate: DateTime.tryParse(map["actualDate"] ?? ""), + expectedVisitDate: DateTime.tryParse(map["expectedDate"] ?? ""), + travelingHours: map["travelingHours"], timer: TimerModel( - startAt: getDate(map["start_date"]), - endAt: getDate(map["end_date"]), - durationInSecond: (int.tryParse(map["working_hours"] ?? "") ?? 0) * 60 *60 + startAt: DateTime.tryParse(map["startDate"] ?? ""), + endAt: DateTime.tryParse(map["endDate"] ?? ""), + durationInSecond: (int.tryParse(map["workingHours"] ?? "") ?? 0) * 60 * 60, ), // contacts: contacts, ppmCheckLists: ppmCheckLists, calibrationTools: calibrationTools, pmKits: pmKits, + signatureNurse: URLs.getFileUrl(map["nurseSignature"]), + signatureEngineer: URLs.getFileUrl(map["engSignature"]), ); } - static getDate(String date){ - return date == null || date.isEmpty - ? null : DateTime.fromMillisecondsSinceEpoch(int.tryParse(date) * 1000); + Pentry copyWith({ + Lookup ppmVisitStatus, + Lookup status, + TimerModel timer, + DateTime actualVisitDate, + DateTime expectedVisitDate, + String travelingHours, + String image, + File imageFile, + List ppmCheckLists, + List calibrationTools, + List pmKits, + String signatureNurse, + String signatureEngineer, + }) { + return Pentry( + ppmVisitStatus: ppmVisitStatus ?? this.ppmVisitStatus, + status: status ?? this.status, + timer: timer ?? this.timer, + actualVisitDate: actualVisitDate ?? this.actualVisitDate, + expectedVisitDate: expectedVisitDate ?? this.expectedVisitDate, + travelingHours: travelingHours ?? this.travelingHours, + image: image ?? this.image, + imageFile: imageFile ?? this.imageFile, + ppmCheckLists: ppmCheckLists ?? this.ppmCheckLists?.map((e) => e.copyWith())?.toList(), + calibrationTools: calibrationTools ?? this.calibrationTools?.map((e) => e.copyWith())?.toList(), + pmKits: pmKits ?? this.pmKits.map((e) => e.copyWith()).toList(), + signatureNurse: signatureNurse ?? this.signatureNurse, + signatureEngineer: signatureEngineer ?? this.signatureEngineer); } -} \ No newline at end of file +} diff --git a/lib/models/pantry/pm_kit.dart b/lib/models/pantry/pm_kit.dart index 0a008e5f..fb3fa857 100644 --- a/lib/models/pantry/pm_kit.dart +++ b/lib/models/pantry/pm_kit.dart @@ -1,6 +1,7 @@ import 'package:test_sa/models/lookup.dart'; -class PMKit{ +class PMKit { + int id; Lookup itemCode; String itemName; String preparationTimeFrame; @@ -9,31 +10,26 @@ class PMKit{ String quantityNeeded; String quantityReserved; - PMKit({ - this.itemCode, - this.itemName, - this.preparationTimeFrame, - this.kitFrequencyDemand, - this.availability, - this.quantityNeeded, - this.quantityReserved - }); + PMKit({this.id, this.itemCode, this.itemName, this.preparationTimeFrame, this.kitFrequencyDemand, this.availability, this.quantityNeeded, this.quantityReserved}); - Map toMap() { + Map toMap(int visitId) { return { - if(itemCode != null) 'itemCode': (itemCode?.id).toString(), - if(itemName != null) 'itemName': itemName, - if(preparationTimeFrame != null) 'preparationTimeFrame': preparationTimeFrame, - if(kitFrequencyDemand != null) 'kitFrequencyDemand': kitFrequencyDemand, - if(availability != null) 'availability': availability, - if(quantityNeeded != null) 'quantityNeeded': quantityNeeded, - if(quantityReserved != null) 'quantityReserved': quantityReserved, + "id": id ?? 0, + "visitId": visitId, + if (itemCode != null) 'partCatalogItemId': (itemCode?.id).toString(), + // if(itemName != null) 'itemName': itemName, + // if(preparationTimeFrame != null) 'preparationTimeFrame': preparationTimeFrame, + // if(kitFrequencyDemand != null) 'kitFrequencyDemand': kitFrequencyDemand, + // if(availability != null) 'availability': availability, + // if(quantityNeeded != null) 'quantityNeeded': quantityNeeded, + // if(quantityReserved != null) 'quantityReserved': quantityReserved, }; } factory PMKit.fromMap(Map map) { return PMKit( - itemCode: Lookup.fromJson(map['itemCode']), + id: map['id'], + itemCode: Lookup(id: map['partCatalogItemId'], name: map["partNumber"]), itemName: map['itemName'] as String, preparationTimeFrame: map['preparationTimeFrame'] as String, kitFrequencyDemand: map['kitFrequencyDemand'] as String, @@ -42,4 +38,26 @@ class PMKit{ quantityReserved: map['quantityReserved'] as String, ); } -} \ No newline at end of file + + PMKit copyWith({ + int id, + Lookup itemCode, + String itemName, + String preparationTimeFrame, + String kitFrequencyDemand, + String availability, + String quantityNeeded, + String quantityReserved, + }) { + return PMKit( + id: id ?? this.id, + itemCode: itemCode ?? this.itemCode, + itemName: itemName ?? this.itemName, + preparationTimeFrame: preparationTimeFrame ?? this.preparationTimeFrame, + kitFrequencyDemand: kitFrequencyDemand ?? this.kitFrequencyDemand, + availability: availability ?? this.availability, + quantityNeeded: quantityNeeded ?? this.quantityNeeded, + quantityReserved: quantityReserved ?? this.quantityReserved, + ); + } +} diff --git a/lib/models/pantry/ppm_check_list.dart b/lib/models/pantry/ppm_check_list.dart index 8f1a14d7..23594b90 100644 --- a/lib/models/pantry/ppm_check_list.dart +++ b/lib/models/pantry/ppm_check_list.dart @@ -1,33 +1,54 @@ import 'package:test_sa/models/lookup.dart'; -class PPMCheckList{ +class PPMCheckList { + int id; Lookup status; String title; String comment; String measuredValue; PPMCheckList({ + this.id, this.title, this.status, this.comment, this.measuredValue, }); - Map toMap() { + Map toMap(int visitId) { return { - if(status != null) 'status': status?.id.toString(), - if(title != null) 'title': title, - if(comment != null) 'comment': comment, - if(measuredValue != null) 'measuredValue': measuredValue, + 'id': id ?? 0, + "visitId": visitId, + if (status != null) 'taskStatusId': status?.id, + if (title != null) 'task': title, + if (comment != null) 'taskComment': comment, + if (measuredValue != null) 'measuredValue': measuredValue, }; } factory PPMCheckList.fromMap(Map map) { return PPMCheckList( - status: Lookup.fromJson(map['status']), - title: map['title'] as String, - comment: map['comment'] as String, + id: map['id'] as int, + status: Lookup(id: map["taskStatusId"], name: map["taskStatusName"]), + title: map['task'] as String, + comment: map['taskComment'] as String, measuredValue: map['measuredValue'] as String, ); } -} \ No newline at end of file + + PPMCheckList copyWith({ + int id, + Lookup status, + String title, + String comment, + String measuredValue, + }) { + return PPMCheckList( + id: id ?? this.id, + status: status ?? this.status, + title: title ?? this.title, + comment: comment ?? this.comment, + measuredValue: measuredValue ?? this.measuredValue, + ); + } +} diff --git a/lib/models/part.dart b/lib/models/part.dart index d75bb493..176811cc 100644 --- a/lib/models/part.dart +++ b/lib/models/part.dart @@ -1,23 +1,33 @@ -class Part{ - String id; +class Part { + int id; + int reportPartID; String code; String name; int quantity; Part({ this.id, + this.reportPartID, this.code, this.name, this.quantity = 1, }); - factory Part.fromJson(Map parsedJson){ + Map toJson() { + return { + "id": reportPartID ?? 0, + "sparePart": {"id": id, "partNo": code, "partName": name}, + "qty": quantity + }; + } + + factory Part.fromJson(Map parsedJson, {Map reportJson}) { return Part( - id: parsedJson["nid"] ?? parsedJson["id"], - code: parsedJson["part_code"] ?? parsedJson["name"], - name: parsedJson["part_name"], - quantity: parsedJson["qty"] == null - ? 1 : int.tryParse(parsedJson["qty"].toString()) ?? 1, + id: parsedJson["id"], + reportPartID: reportJson != null ? reportJson["id"] : null, + code: parsedJson["partNo"], + name: parsedJson["partName"], + quantity: reportJson != null ? (reportJson["qty"] ?? 1).toInt() : 1, ); } -} \ No newline at end of file +} diff --git a/lib/models/service_report.dart b/lib/models/service_report.dart index 81047ec1..a5fed419 100644 --- a/lib/models/service_report.dart +++ b/lib/models/service_report.dart @@ -1,149 +1,245 @@ -import 'dart:convert'; +import 'dart:typed_data'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/device/device.dart'; +import 'package:test_sa/models/engineer.dart'; +import 'package:test_sa/models/fault_description.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/part.dart'; +import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/models/timer_model.dart'; class ServiceReport { - String id; - String operatingHours; + int id; + double operatingHours; DateTime visitDate; - DateTime endDate; - Lookup serviceType; + DateTime returnToService; + + // DateTime endDate; + // DateTime startDate; + Lookup assetType; Lookup callLastSituation; - Lookup status; + Lookup currentSituation; + Lookup repairLocation; + Engineer engineer; + Lookup equipmentStatus; Lookup type; Lookup reason; - String faultDescription; + int faultDescriptionId; String workPreformed; - //String workHours; - String travelingHours; + + num workingHours; + double travelingHours; String invoiceNumber; String invoiceCode; List parts; - String image; + List image; Device device; String quantity; String jobSheetNumber; TimerModel timer; + String signatureNurse; + String signatureEngineer; + String comment; + Uint8List localNurseSignature; + Uint8List localEngineerSignature; + num travelingExpense; + String reviewComment; + FaultDescription faultDescription; - ServiceReport({ - this.id, - this.visitDate, - this.endDate, - this.serviceType, - this.status, - this.type, - this.faultDescription, - //this.workHours, - this.travelingHours, - this.parts, - this.workPreformed, - this.reason, - this.operatingHours, - this.callLastSituation, - this.jobSheetNumber, - this.image, - this.device, - this.invoiceCode, - this.invoiceNumber, - this.quantity = "1", - this.timer, - }); + ServiceReport( + {this.id, + this.visitDate, + // this.endDate, + this.assetType, + this.equipmentStatus, + this.type, + this.faultDescriptionId, + this.workingHours, + this.travelingHours, + this.parts, + this.engineer, + this.workPreformed, + this.reason, + this.operatingHours, + this.callLastSituation, + this.currentSituation, + this.jobSheetNumber, + this.image, + this.device, + this.invoiceCode, + this.invoiceNumber, + this.quantity = "1", + this.timer, + this.signatureNurse, + this.signatureEngineer, + this.localNurseSignature, + this.localEngineerSignature, + this.comment, + this.repairLocation, + this.travelingExpense, + // this.startDate, + this.reviewComment, + this.faultDescription, + this.returnToService}); - Map toMap(){ - Map _map = {}; - if(id != null) _map["id"] = id; - if(visitDate != null) _map["visit_date"] = (visitDate.millisecondsSinceEpoch ~/ 1000).toString(); - if(serviceType != null) _map["service_type"] = serviceType.id.toString(); - if(status != null) _map["status"] = status.id.toString(); - if(type != null) _map["service_report_type"] = type.id.toString(); - if(faultDescription != null && faultDescription.isNotEmpty) _map["fault_description"] = faultDescription; + Map toMap(ServiceRequest request) { + Map _map = {}; + if (id != null) _map["id"] = id; + if (visitDate != null) _map["visitDate"] = visitDate.toIso8601String(); + if (returnToService != null) _map["replacementDate"] = returnToService.toIso8601String(); + + //if(serviceType != null) _map["service_type"] = serviceType.id.toString(); + if (equipmentStatus != null) _map["equipmentStatus"] = equipmentStatus?.toMap(); + if (type != null) _map["typeOfWO"] = type?.toMap(); + if (assetType != null) _map["TypeOfWO"] = assetType?.toMap(); + //if(faultDescriptionId != null && faultDescriptionId.isNotEmpty) _map["fault_description"] = faultDescriptionId; //if(workHours != null && workHours.isNotEmpty) _map["working_hours"] = workHours; - if(timer != null){ - _map["start_time"] = (timer.startAt.millisecondsSinceEpoch / 1000).toStringAsFixed(0); - _map["end_time"] = ((timer.endAt ?? DateTime.now()).millisecondsSinceEpoch / 1000).toStringAsFixed(0); - _map["working_hours"] = (timer.durationInSecond / 60 / 60).toStringAsFixed(5); + if (timer != null) { + _map["startofWorkTime"] = timer.startAt.toIso8601String(); + _map["endofWorkTime"] = (timer.endAt ?? DateTime.now()).toIso8601String(); + _map["workingHours"] = (timer.durationInSecond / 60 / 60).toStringAsFixed(5); + } + if (travelingHours != null && travelingHours.toString().isNotEmpty) _map["travelingHours"] = travelingHours; + // if(workPreformed != null && workPreformed.isNotEmpty){ + // _map["faultDescription"] = { + // "id":faultDescriptionId ?? 0, + // "workPerformed":workPreformed + // }; + // } + _map["faultDescription"] = faultDescription?.id == null ? null : {"id": faultDescription?.id ?? 0, "workPerformed": faultDescription?.workPerformed}; + if (travelingHours != null) _map["travelingHours"] = travelingHours; + // if (workingHours != null) _map["workingHours"] = workingHours; + // if (workPreformed != null && workPreformed.isNotEmpty) { + // _map["faultDescription"] = faultDescription.toJson(); + // } + if (jobSheetNumber != null && jobSheetNumber.isNotEmpty) _map["job_sheet_no"] = jobSheetNumber; + if (parts != null && parts.isNotEmpty) { + _map["sparePartsWorkOrders"] = parts.map((e) => e.toJson()).toList(); } - if(travelingHours != null && travelingHours.isNotEmpty) _map["traveling_hours"] = travelingHours; - if(workPreformed != null && workPreformed.isNotEmpty) _map["work_performed"] = workPreformed; - if(jobSheetNumber != null && jobSheetNumber.isNotEmpty) _map["job_sheet_no"] = jobSheetNumber; - if(parts != null && parts.isNotEmpty){ - Map _partsMap = {}; - parts.forEach((part) { - if(part.id.isNotEmpty) - _partsMap[part.id] = part.quantity; - }); - _map["parts"] = json.encode(_partsMap); + if (device != null && device.id != null) { + _map["callRequest"] = { + "id": request.id, + "asset": device?.toMap(assetType), + }; + _map["callRequest"]["asset"]["invoiceNumber"] = invoiceNumber; } - if(device?.id != null && device.id != null) _map["eq_id"] = device.id; - if(quantity != null && quantity.isNotEmpty) _map["qty"] = quantity; - if(endDate != null) _map["end_date"] = (endDate.millisecondsSinceEpoch ~/ 1000).toString(); - if(reason != null) _map["reasons"] = reason.id.toString(); - if(operatingHours != null && operatingHours.isNotEmpty) _map["operation_hours"] = operatingHours; - if(callLastSituation != null) _map["call_last_situtation"] = callLastSituation.id.toString(); - if(image != null) _map["image"] = image; - if(invoiceCode != null) _map["invoice_no"] = invoiceCode; - if(invoiceNumber != null) _map["invoice_code"] = invoiceNumber; + _map["AssignedEmployee"] = engineer?.toMap(); + _map["repairLocation"] = repairLocation?.toMap(); + //if(quantity != null && quantity.isNotEmpty) _map["qty"] = quantity; + //if(endDate != null) _map["end_date"] = (endDate.millisecondsSinceEpoch ~/ 1000).toString(); + if (reason != null) _map["reason"] = reason.toMap(); + //if(operatingHours != null && operatingHours.isNotEmpty) _map["operation_hours"] = operatingHours; + if (callLastSituation != null) _map["calllastSituation"] = callLastSituation.toMap(); + if (currentSituation != null) _map["currentSituation"] = currentSituation.toMap(); + //if(image != null) _map["image"] = image; + //if(invoiceCode != null) _map["invoice_no"] = invoiceCode; + //if(invoiceNumber != null) _map["invoice_code"] = invoiceNumber; + if (image != null) { + _map["attachmentsWorkOrder"] = image.map((e) => {"name": e}).toList(); + print(_map["attachmentsWorkOrder"]); + } + _map["nurseSignature"] = signatureNurse; + _map["engSignature"] = signatureEngineer; + _map["comment"] = comment; + _map["travelingExpenses"] = travelingExpense; + // _map["startofWorkTime"] = startDate.toIso8601String(); + // _map["endofWorkTime"] = endDate.toIso8601String(); + // _map["workingHours"] = endDate?.difference(startDate)?.inHours ?? 0; + if (timer?.startAt != null) _map["startofWorkTime"] = timer?.startAt?.toIso8601String(); + if (timer?.endAt != null) _map["endofWorkTime"] = timer?.endAt?.toIso8601String(); + _map["workingHours"] = workingHours; + _map["reviewComment"] = reviewComment; return _map; } - bool validate(){ - if(visitDate == null) return false; - if(serviceType == null) return false; - if(status == null) return false; - if(type == null) return false; - if(callLastSituation == null) return false; - if(callLastSituation?.id == 12){ - if(invoiceCode != null || invoiceCode?.isEmpty == true) return false; - if(invoiceNumber != null || invoiceNumber?.isEmpty== true ) return false; + Future validate() async { + if (visitDate == null) { + await Fluttertoast.showToast(msg: "Visit Date Required"); + return false; + } + if (returnToService == null) { + await Fluttertoast.showToast(msg: "Return To Service Date Required"); + return false; + } + if (timer?.startAt == null) { + await Fluttertoast.showToast(msg: "Working Hours Required"); + return false; } - if(parts == null) return false; + if (timer?.endAt == null) { + await Fluttertoast.showToast(msg: "Please Stop The Timer"); + return false; + } + //if(serviceType == null) return false; + if (equipmentStatus == null) return false; + //if (type == null && assetType == null) return false; + // if (engineer == null) return false; + if (callLastSituation == null) return false; + if (callLastSituation?.value == 12) { + // if(invoiceCode != null || invoiceCode?.isEmpty == true) return false; + if (invoiceNumber != null || invoiceNumber?.isEmpty == true) return false; + } + if (parts == null) return false; //if(endDate == null) return false; - //if(reason == null) return false; - if((device?.id == null || device.id.isEmpty) && type?.id != 1) return false; + if (reason == null) return false; + //todo uncoment this line + //if((device?.id == null || device.id.isEmpty) && type?.id != 1) return false; //if(quantity == null || quantity.isEmpty) return false; //if(image == null) return false; return true; } - factory ServiceReport.fromJson(Map parsedJson,String id){ - List _parts = []; - if(parsedJson["parts"] != null){ - if(parsedJson["parts"][0]["id"] != null){ - List partsList = parsedJson["parts"]; - _parts = partsList.map((e) => Part.fromJson(e)).toList(); - } - + factory ServiceReport.fromJson(Map parsedJson, int id) { + List _parts = []; + if (parsedJson["sparePartsWorkOrders"] != null) { + if ((parsedJson["sparePartsWorkOrders"] as List).isNotEmpty && parsedJson["sparePartsWorkOrders"][0]["id"] != null) { + List partsList = parsedJson["sparePartsWorkOrders"]; + _parts = partsList.map((e) => Part.fromJson(e["sparePart"], reportJson: e)).toList(); } + } return ServiceReport( id: id, - serviceType: Lookup.fromJson(parsedJson["service_type"]), - callLastSituation: Lookup.fromJson(parsedJson["call_last_situtation"]), - reason: Lookup.fromJson(parsedJson["reasons"]), - status: Lookup.fromJson(parsedJson["service_report_status"]), - type: Lookup.fromJson(parsedJson["service_report_type"]), - faultDescription: parsedJson["fault_description"], - endDate:getDate(parsedJson["end_date"]), - invoiceCode: parsedJson["invoice_code"], - invoiceNumber: parsedJson["invoice_no"], - jobSheetNumber: parsedJson["job_sheet_no"], - operatingHours: parsedJson["operation_hours"], + assetType: Lookup.fromJson(parsedJson["assetType"]), + callLastSituation: Lookup.fromJson(parsedJson["calllastSituation"]), + currentSituation: Lookup.fromJson(parsedJson["currentSituation"]), + repairLocation: Lookup.fromJson(parsedJson["repairLocation"]), + reason: Lookup.fromJson(parsedJson["reason"]), + equipmentStatus: Lookup.fromJson(parsedJson["equipmentStatus"]), + type: Lookup.fromJson(parsedJson["typeOfWO"]), + faultDescription: parsedJson['faultDescription'] != null ? FaultDescription.fromJson(parsedJson['faultDescription']) : null, + + // faultDescription: parsedJson["faultDescription"], + // startDate: DateTime.tryParse(parsedJson["startofWorkTime"] ?? ""), + // endDate: DateTime.tryParse(parsedJson["endofWorkTime"] ?? ""), + //invoiceCode: parsedJson["invoice_code"], + //invoiceNumber: parsedJson["invoice_no"], + //jobSheetNumber: parsedJson["job_sheet_no"], + // workingHours: parsedJson["workingHours"], + engineer: Engineer.fromJson(parsedJson["assignedEmployee"]), parts: _parts, - quantity: parsedJson["nid"], - travelingHours: parsedJson["traveling_hours"], - visitDate: getDate(parsedJson["visit_date"]), - //workHours: parsedJson["working_hours"], + //quantity: parsedJson["nid"], + travelingHours: parsedJson["travelingHours"], + travelingExpense: parsedJson["travelingExpenses"], + visitDate: DateTime.tryParse(parsedJson["visitDate"]), + returnToService: DateTime.tryParse(parsedJson["replacementDate"] ?? ""), + workingHours: parsedJson["workingHours"], timer: TimerModel( - durationInSecond: (int.tryParse(parsedJson["working_hours"] ?? "") ?? 0) * 60 *60), - workPreformed: parsedJson["work_performed"], - device: parsedJson["eq_nid"] == null ? null : Device(id: parsedJson["eq_nid"],serialNumber: parsedJson["eq_serial"]) + startAt: DateTime.tryParse(parsedJson["startofWorkTime"] ?? ""), + endAt: DateTime.tryParse(parsedJson["endofWorkTime"] ?? ""), + durationInSecond: ((parsedJson["workingHours"] ?? 0) * 60 * 60).toInt(), + ), + //workPreformed: parsedJson["work_performed"], + device: Device.fromJson(parsedJson["callRequest"]["asset"]), + signatureNurse: URLs.getFileUrl(parsedJson["nurseSignature"]), + signatureEngineer: URLs.getFileUrl(parsedJson["engSignature"]), + comment: parsedJson['comment'], + reviewComment: parsedJson['reviewComment'], ); } - static getDate(String date){ - return date == null || date.isEmpty - ? null : DateTime.fromMillisecondsSinceEpoch(int.tryParse(date) * 1000); - } -} \ No newline at end of file +// static getDate(String date){ +// return date == null || date.isEmpty +// ? null : DateTime.fromMillisecondsSinceEpoch(int.tryParse(date) * 1000); +// } +} diff --git a/lib/models/service_request/search_work_order.dart b/lib/models/service_request/search_work_order.dart new file mode 100644 index 00000000..7f4efa55 --- /dev/null +++ b/lib/models/service_request/search_work_order.dart @@ -0,0 +1,2932 @@ +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/timer_model.dart'; + +import '../fault_description.dart'; + +class SearchWorkOrder { + SearchWorkOrder({ + this.id, + this.parentWOId, + this.workOrderNo, + this.workOrderYear, + this.workOrderSequennce, + this.callRequest, + this.assetType, + this.assignedEmployee, + this.visitDate, + this.assistantEmployees, + this.supplier, + this.vendorTicketNumber, + this.contactPersonWorkOrders, + this.calllastSituation, + this.currentSituation, + this.repairLocation, + this.reason, + // this.startofWorkTime, + // this.endofWorkTime, + this.workingHours, + this.travelingHours, + this.travelingExpenses, + this.faultDescription, + this.sparePartsWorkOrders, + this.reviewComment, + this.comment, + this.attachmentsWorkOrder, + this.equipmentStatus, + this.suppEngineerWorkOrders, + this.engSignature, + this.nurseSignature, + this.woParentDto, + this.timer, + }); + + SearchWorkOrder.fromJson(dynamic json) { + id = json['id']; + parentWOId = json['parentWOId']; + workOrderNo = json['workOrderNo']; + workOrderYear = json['workOrderYear']; + workOrderSequennce = json['workOrderSequennce']; + callRequest = json['callRequest'] != null ? CallRequest.fromJson(json['callRequest']) : null; + assetType = json['assetType'] != null ? Lookup.fromJson(json['assetType']) : null; + assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null; + visitDate = json['visitDate']; + if (json['assistantEmployees'] != null) { + assistantEmployees = []; + json['assistantEmployees'].forEach((v) { + assistantEmployees.add(AssistantEmployees.fromJson(v)); + }); + } + supplier = json['supplier'] != null ? SupplierModel.fromJson(json['supplier']) : null; + vendorTicketNumber = json['vendorTicketNumber']; + if (json['contactPersonWorkOrders'] != null) { + contactPersonWorkOrders = []; + json['contactPersonWorkOrders'].forEach((v) { + contactPersonWorkOrders.add(ContactPersonWorkOrders.fromJson(v)); + }); + } + calllastSituation = json['calllastSituation'] != null ? Lookup.fromJson(json['calllastSituation']) : null; + currentSituation = json['currentSituation'] != null ? Lookup.fromJson(json['currentSituation']) : null; + repairLocation = json['repairLocation'] != null ? Lookup.fromJson(json['repairLocation']) : null; + reason = json['reason'] != null ? Lookup.fromJson(json['reason']) : null; + // startofWorkTime = json['startofWorkTime']; + // endofWorkTime = json['endofWorkTime']; + if (json['startofWorkTime'] != null || json['endofWorkTime'] != null) { + timer = TimerModel(); + } + if (json['startofWorkTime'] != null) timer.startAt = DateTime.tryParse(json['startofWorkTime']); + if (json['endofWorkTime'] != null) timer.endAt = DateTime.tryParse(json['endofWorkTime']); + workingHours = json['workingHours']; + travelingHours = json['travelingHours']; + travelingExpenses = json['travelingExpenses']; + faultDescription = json['faultDescription'] != null ? FaultDescription.fromJson(json['faultDescription']) : null; + if (json['sparePartsWorkOrders'] != null) { + sparePartsWorkOrders = []; + json['sparePartsWorkOrders'].forEach((v) { + sparePartsWorkOrders.add(SparePartsWorkOrders.fromJson(v)); + }); + } + reviewComment = json['reviewComment']; + comment = json['comment']; + if (json['attachmentsWorkOrder'] != null) { + attachmentsWorkOrder = []; + json['attachmentsWorkOrder'].forEach((v) { + attachmentsWorkOrder.add(AttachmentsWorkOrder.fromJson(v)); + }); + } + equipmentStatus = json['equipmentStatus'] != null ? Lookup.fromJson(json['equipmentStatus']) : null; + if (json['suppEngineerWorkOrders'] != null) { + suppEngineerWorkOrders = []; + json['suppEngineerWorkOrders'].forEach((v) { + suppEngineerWorkOrders.add(SuppEngineerWorkOrders.fromJson(v)); + }); + } + engSignature = json['engSignature']; + nurseSignature = json['nurseSignature']; + woParentDto = json['woParentDto'] != null ? WoParentDto.fromJson(json['woParentDto']) : null; + } + + void copyFrom(SearchWorkOrder wo) { + parentWOId = wo.parentWOId ?? parentWOId; + workOrderNo = wo.workOrderNo ?? workOrderNo; + workOrderYear = wo.workOrderYear ?? workOrderYear; + workOrderSequennce = wo.workOrderSequennce ?? workOrderSequennce; + callRequest = wo.callRequest ?? callRequest; + if (wo.assetType != null) assetType = Lookup.fromJson((wo.assetType)?.toMap() ?? {}); + if (wo.assignedEmployee != null) assignedEmployee = AssignedEmployee.fromJson((wo.assignedEmployee)?.toJson() ?? {}); + visitDate = wo.visitDate ?? visitDate; + assistantEmployees = (wo.assistantEmployees ?? assistantEmployees) + ?.map((e) => AssistantEmployees.fromJson({ + "id": e?.id, + "user": {"name": e?.user?.name, "id": (e?.user?.id) ?? "0"} + })) + ?.toList() ?? + []; + if (wo.supplier != null) supplier = SupplierModel.fromJson((wo.supplier)?.toJson() ?? {}); + vendorTicketNumber = wo.vendorTicketNumber ?? vendorTicketNumber; + contactPersonWorkOrders = (wo.contactPersonWorkOrders ?? contactPersonWorkOrders)?.map((e) => ContactPersonWorkOrders.fromJson(e?.toJson() ?? {}))?.toList() ?? []; + calllastSituation = Lookup.fromJson((wo.calllastSituation ?? calllastSituation)?.toMap() ?? {}); + if (wo.currentSituation != null) currentSituation = Lookup.fromJson((wo.currentSituation)?.toMap() ?? {}); + repairLocation = Lookup.fromJson((wo.repairLocation ?? repairLocation)?.toMap() ?? {}); + reason = Lookup.fromJson((wo.reason ?? reason)?.toMap() ?? {}); + // startofWorkTime = wo.startofWorkTime ?? startofWorkTime; + // endofWorkTime = wo.endofWorkTime ?? endofWorkTime; + timer = wo.timer ?? timer; + workingHours = wo.workingHours ?? workingHours; + travelingHours = wo.travelingHours ?? travelingHours; + travelingExpenses = wo.travelingExpenses ?? travelingExpenses; + faultDescription = FaultDescription.fromJson((wo.faultDescription ?? faultDescription)?.toJson() ?? {}); + sparePartsWorkOrders = (wo.sparePartsWorkOrders ?? sparePartsWorkOrders)?.map((e) => SparePartsWorkOrders.fromJson(e?.toJson() ?? {}))?.toList() ?? []; + reviewComment = wo.reviewComment ?? reviewComment; + comment = wo.comment ?? comment; + attachmentsWorkOrder = (wo.attachmentsWorkOrder ?? attachmentsWorkOrder)?.map((e) => AttachmentsWorkOrder.fromJson(e?.toJson() ?? {}))?.toList() ?? []; + equipmentStatus = Lookup.fromJson((wo.equipmentStatus ?? equipmentStatus)?.toMap() ?? {}); + suppEngineerWorkOrders = (wo.suppEngineerWorkOrders ?? suppEngineerWorkOrders)?.map((e) => SuppEngineerWorkOrders.fromJson(e?.toJson() ?? {}))?.toList() ?? []; + engSignature = wo.engSignature ?? engSignature; + nurseSignature = wo.nurseSignature ?? nurseSignature; + woParentDto = wo.woParentDto ?? woParentDto; + } + + num id; + num parentWOId; + String workOrderNo; + num workOrderYear; + num workOrderSequennce; + CallRequest callRequest; + Lookup assetType; + AssignedEmployee assignedEmployee; + String visitDate; + List assistantEmployees; + SupplierModel supplier; + String vendorTicketNumber; + List contactPersonWorkOrders; + Lookup calllastSituation; + Lookup currentSituation; + Lookup repairLocation; + Lookup reason; + + // String startofWorkTime; + // String endofWorkTime; + num workingHours; + num travelingHours; + num travelingExpenses; + FaultDescription faultDescription; + List sparePartsWorkOrders; + String reviewComment; + String comment; + List attachmentsWorkOrder; + Lookup equipmentStatus; + List suppEngineerWorkOrders; + String engSignature; + String nurseSignature; + WoParentDto woParentDto; + TimerModel timer; + + SearchWorkOrder copyWith({ + num id, + num parentWOId, + String workOrderNo, + num workOrderYear, + num workOrderSequennce, + CallRequest callRequest, + Lookup assetType, + AssignedEmployee assignedEmployee, + String visitDate, + List assistantEmployees, + SupplierModel supplier, + String vendorTicketNumber, + List contactPersonWorkOrders, + Lookup calllastSituation, + Lookup currentSituation, + Lookup repairLocation, + Lookup reason, + // String startofWorkTime, + // String endofWorkTime, + num workingHours, + num travelingHours, + num travelingExpenses, + FaultDescription faultDescription, + List sparePartsWorkOrders, + String reviewComment, + String comment, + List attachmentsWorkOrder, + Lookup equipmentStatus, + List suppEngineerWorkOrders, + String engSignature, + String nurseSignature, + WoParentDto woParentDto, + TimerModel timer, + }) => + SearchWorkOrder( + id: id ?? this.id, + parentWOId: parentWOId ?? this.parentWOId, + workOrderNo: workOrderNo ?? this.workOrderNo, + workOrderYear: workOrderYear ?? this.workOrderYear, + workOrderSequennce: workOrderSequennce ?? this.workOrderSequennce, + callRequest: callRequest ?? this.callRequest, + assetType: assetType ?? this.assetType, + assignedEmployee: assignedEmployee ?? this.assignedEmployee, + visitDate: visitDate ?? this.visitDate, + assistantEmployees: assistantEmployees ?? this.assistantEmployees, + supplier: supplier ?? this.supplier, + vendorTicketNumber: vendorTicketNumber ?? this.vendorTicketNumber, + contactPersonWorkOrders: contactPersonWorkOrders ?? this.contactPersonWorkOrders, + calllastSituation: calllastSituation ?? this.calllastSituation, + currentSituation: currentSituation ?? this.currentSituation, + repairLocation: repairLocation ?? this.repairLocation, + reason: reason ?? this.reason, + // startofWorkTime: startofWorkTime ?? this.startofWorkTime, + // endofWorkTime: endofWorkTime ?? this.endofWorkTime, + workingHours: workingHours ?? this.workingHours, + travelingHours: travelingHours ?? this.travelingHours, + travelingExpenses: travelingExpenses ?? this.travelingExpenses, + faultDescription: faultDescription ?? this.faultDescription, + sparePartsWorkOrders: sparePartsWorkOrders ?? this.sparePartsWorkOrders, + reviewComment: reviewComment ?? this.reviewComment, + comment: comment ?? this.comment, + attachmentsWorkOrder: attachmentsWorkOrder ?? this.attachmentsWorkOrder, + equipmentStatus: equipmentStatus ?? this.equipmentStatus, + suppEngineerWorkOrders: suppEngineerWorkOrders ?? this.suppEngineerWorkOrders, + engSignature: engSignature ?? this.engSignature, + nurseSignature: nurseSignature ?? this.nurseSignature, + woParentDto: woParentDto ?? this.woParentDto, + timer: timer ?? this.timer, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['parentWOId'] = parentWOId; + map['workOrderNo'] = workOrderNo; + map['workOrderYear'] = workOrderYear; + map['workOrderSequennce'] = workOrderSequennce; + if (callRequest != null) { + map['callRequest'] = callRequest.toJson(); + } + if (assetType != null) { + map['assetType'] = assetType.toMap(); + } + if (assignedEmployee != null) { + map['assignedEmployee'] = assignedEmployee.toJson(); + } + map['visitDate'] = visitDate; + if (assistantEmployees != null) { + map['assistantEmployees'] = assistantEmployees.map((v) => v?.toJson()).toList(); + } + if (supplier != null) { + map['supplier'] = supplier.toJson(); + } + map['vendorTicketNumber'] = vendorTicketNumber; + if (contactPersonWorkOrders != null) { + map['contactPersonWorkOrders'] = contactPersonWorkOrders.map((v) => v.toJson()).toList(); + } + if (calllastSituation != null) { + map['calllastSituation'] = calllastSituation.toMap(); + } + map['currentSituation'] = currentSituation?.toMap(); + if (repairLocation?.id != null) { + map['repairLocation'] = repairLocation.toMap(); + } + if (reason != null) { + map['reason'] = reason.toMap(); + } + // map['startofWorkTime'] = startofWorkTime; + // map['endofWorkTime'] = endofWorkTime; + map['startofWorkTime'] = timer?.startAt?.toIso8601String(); + map['endofWorkTime'] = timer?.endAt?.toIso8601String(); + map['workingHours'] = workingHours; + map['travelingHours'] = travelingHours; + map['travelingExpenses'] = travelingExpenses; + + if (faultDescription?.id != null) { + map['faultDescription'] = faultDescription.toJson(); + } + if (sparePartsWorkOrders != null) { + map['sparePartsWorkOrders'] = sparePartsWorkOrders.map((v) => v.toJson()).toList(); + } + map['reviewComment'] = reviewComment; + map['comment'] = comment; + if (attachmentsWorkOrder != null) { + map['attachmentsWorkOrder'] = attachmentsWorkOrder.map((v) => v.toJson()).toList(); + } + if (equipmentStatus != null) { + map['equipmentStatus'] = equipmentStatus.toMap(); + } + if (suppEngineerWorkOrders != null) { + map['suppEngineerWorkOrders'] = suppEngineerWorkOrders.map((v) => v.toJson()).toList(); + } + map['engSignature'] = engSignature; + map['nurseSignature'] = nurseSignature; + if (woParentDto != null) { + map['woParentDto'] = woParentDto.toJson(); + } + return map; + } +} + +class WoParentDto { + WoParentDto({ + this.callLastSituation, + this.supplier, + this.assetType, + this.vendorTicketNumber, + this.callId, + this.id, + this.stepsWorkOrderDto, + this.suppEngineerWorkOrders, + this.equipmentStatus, + this.currentSituation, + }); + + WoParentDto.fromJson(dynamic json) { + callLastSituation = json['callLastSituation'] != null ? Lookup.fromJson(json['callLastSituation']) : null; + supplier = json['supplier'] != null ? SupplierModel.fromJson(json['supplier']) : null; + assetType = json['assetType'] != null ? Lookup.fromJson(json['assetType']) : null; + vendorTicketNumber = json['vendorTicketNumber']; + callId = json['callId']; + id = json['id']; + stepsWorkOrderDto = json['stepsWorkOrderDto'] != null ? StepsWorkOrderDto.fromJson(json['stepsWorkOrderDto']) : null; + if (json['suppEngineerWorkOrders'] != null) { + suppEngineerWorkOrders = []; + json['suppEngineerWorkOrders'].forEach((v) { + suppEngineerWorkOrders.add(SuppEngineerWorkOrders.fromJson(v)); + }); + } + equipmentStatus = json['equipmentStatus'] != null ? Lookup.fromJson(json['equipmentStatus']) : null; + currentSituation = json['currentSituation'] != null ? Lookup.fromJson(json['currentSituation']) : null; + } + + Lookup callLastSituation; + SupplierModel supplier; + Lookup assetType; + String vendorTicketNumber; + num callId; + num id; + StepsWorkOrderDto stepsWorkOrderDto; + List suppEngineerWorkOrders; + Lookup equipmentStatus; + Lookup currentSituation; + + WoParentDto copyWith({ + Lookup callLastSituation, + SupplierModel supplier, + Lookup assetType, + String vendorTicketNumber, + num callId, + num id, + StepsWorkOrderDto stepsWorkOrderDto, + List suppEngineerWorkOrders, + Lookup equipmentStatus, + Lookup currentSituation, + }) => + WoParentDto( + callLastSituation: callLastSituation ?? this.callLastSituation, + supplier: supplier ?? this.supplier, + assetType: assetType ?? this.assetType, + vendorTicketNumber: vendorTicketNumber ?? this.vendorTicketNumber, + callId: callId ?? this.callId, + id: id ?? this.id, + stepsWorkOrderDto: stepsWorkOrderDto ?? this.stepsWorkOrderDto, + suppEngineerWorkOrders: suppEngineerWorkOrders ?? this.suppEngineerWorkOrders, + equipmentStatus: equipmentStatus ?? this.equipmentStatus, + currentSituation: currentSituation ?? this.currentSituation, + ); + + Map toJson() { + final map = {}; + if (callLastSituation != null) { + map['callLastSituation'] = callLastSituation.toMap(); + } + if (supplier != null) { + map['supplier'] = supplier.toJson(); + } + if (assetType != null) { + map['assetType'] = assetType.toMap(); + } + map['vendorTicketNumber'] = vendorTicketNumber; + map['callId'] = callId ?? 0; + map['id'] = id ?? 0; + if (stepsWorkOrderDto != null) { + map['stepsWorkOrderDto'] = stepsWorkOrderDto.toJson(); + } + if (suppEngineerWorkOrders != null) { + map['suppEngineerWorkOrders'] = suppEngineerWorkOrders.map((v) => v.toJson()).toList(); + } + if (equipmentStatus != null) { + map['equipmentStatus'] = equipmentStatus.toMap(); + } + if (currentSituation != null) { + map['currentSituation'] = currentSituation.toMap(); + } + return map; + } +} + +class SuppEngineerWorkOrders { + SuppEngineerWorkOrders({ + this.id, + this.supplierContactId, + this.personName, + this.personRoleName, + this.contact, + this.externalEngCode, + this.email, + }); + + SuppEngineerWorkOrders.fromJson(dynamic json) { + id = json['id']; + supplierContactId = json['supplierContactId']; + personName = json['personName']; + personRoleName = json['personRoleName']; + contact = json['contact']; + externalEngCode = json['externalEngCode']; + email = json['email']; + } + + num id; + num supplierContactId; + String personName; + String personRoleName; + String contact; + String externalEngCode; + String email; + + SuppEngineerWorkOrders copyWith({ + num id, + num supplierContactId, + String personName, + String personRoleName, + String contact, + String externalEngCode, + String email, + }) => + SuppEngineerWorkOrders( + id: id ?? this.id, + supplierContactId: supplierContactId ?? this.supplierContactId, + personName: personName ?? this.personName, + personRoleName: personRoleName ?? this.personRoleName, + contact: contact ?? this.contact, + externalEngCode: externalEngCode ?? this.externalEngCode, + email: email ?? this.email, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['supplierContactId'] = supplierContactId; + map['personName'] = personName; + map['personRoleName'] = personRoleName; + map['contact'] = contact; + map['externalEngCode'] = externalEngCode; + map['email'] = email; + return map; + } +} + +class StepsWorkOrderDto { + StepsWorkOrderDto({ + this.sequence, + this.id, + this.name, + this.statusValue, + this.typeTransaction, + this.processed, + this.parentWOId, + this.callId, + }); + + StepsWorkOrderDto.fromJson(dynamic json) { + sequence = json['sequence']; + id = json['id']; + name = json['name']; + statusValue = json['statusValue']; + typeTransaction = json['typeTransaction']; + processed = json['processed']; + parentWOId = json['parentWOId']; + callId = json['callId']; + } + + num sequence; + num id; + String name; + num statusValue; + String typeTransaction; + bool processed; + num parentWOId; + num callId; + + StepsWorkOrderDto copyWith({ + num sequence, + num id, + String name, + num statusValue, + String typeTransaction, + bool processed, + num parentWOId, + num callId, + }) => + StepsWorkOrderDto( + sequence: sequence ?? this.sequence, + id: id ?? this.id, + name: name ?? this.name, + statusValue: statusValue ?? this.statusValue, + typeTransaction: typeTransaction ?? this.typeTransaction, + processed: processed ?? this.processed, + parentWOId: parentWOId ?? this.parentWOId, + callId: callId ?? this.callId, + ); + + Map toJson() { + final map = {}; + map['sequence'] = sequence; + map['id'] = id ?? 0; + map['name'] = name; + map['statusValue'] = statusValue; + map['typeTransaction'] = typeTransaction; + map['processed'] = processed; + map['parentWOId'] = parentWOId; + map['callId'] = callId; + return map; + } +} + +class SupplierModel { + SupplierModel({ + this.id, + this.suppliername, + this.name, + this.website, + this.email, + this.code, + this.suppNo, + this.suppStatusId, + this.cityId, + this.person, + this.comment, + this.zipcode, + this.contact, + this.telephones, + this.faxes, + this.addresses, + this.attachments, + this.suppPersons, + this.suppTCodes, + }); + + SupplierModel.fromJson(dynamic json) { + id = json['id'] ?? 0; + suppliername = json['suppliername']; + name = json['name']; + website = json['website']; + email = json['email']; + code = json['code']; + suppNo = json['suppNo']; + suppStatusId = json['suppStatusId']; + cityId = json['cityId']; + person = json['person']; + comment = json['comment']; + zipcode = json['zipcode']; + contact = json['contact']; + if (json['telephones'] != null) { + telephones = []; + json['telephones'].forEach((v) { + telephones.add(Telephones.fromJson(v)); + }); + } + if (json['faxes'] != null) { + faxes = []; + json['faxes'].forEach((v) { + faxes.add(Faxes.fromJson(v)); + }); + } + if (json['addresses'] != null) { + addresses = []; + json['addresses'].forEach((v) { + addresses.add(Addresses.fromJson(v)); + }); + } + if (json['attachments'] != null) { + attachments = []; + json['attachments'].forEach((v) { + attachments.add(Attachments.fromJson(v)); + }); + } + if (json['suppPersons'] != null) { + suppPersons = []; + json['suppPersons'].forEach((v) { + suppPersons.add(SuppPersons.fromJson(v)); + }); + } + if (json['suppTCodes'] != null) { + suppTCodes = []; + json['suppTCodes'].forEach((v) { + suppTCodes.add(SuppTCodes.fromJson(v)); + }); + } + } + + num id; + String suppliername; + String name; + String website; + String email; + String code; + num suppNo; + num suppStatusId; + num cityId; + String person; + String comment; + num zipcode; + String contact; + List telephones; + List faxes; + List addresses; + List attachments; + List suppPersons; + List suppTCodes; + + SupplierModel copyWith({ + num id, + String suppliername, + String name, + String website, + String email, + String code, + num suppNo, + num suppStatusId, + num cityId, + String person, + String comment, + num zipcode, + String contact, + List telephones, + List faxes, + List addresses, + List attachments, + List suppPersons, + List suppTCodes, + }) => + SupplierModel( + id: id ?? this.id ?? 0, + suppliername: suppliername ?? this.suppliername, + name: name ?? this.name, + website: website ?? this.website, + email: email ?? this.email, + code: code ?? this.code, + suppNo: suppNo ?? this.suppNo, + suppStatusId: suppStatusId ?? this.suppStatusId, + cityId: cityId ?? this.cityId, + person: person ?? this.person, + comment: comment ?? this.comment, + zipcode: zipcode ?? this.zipcode, + contact: contact ?? this.contact, + telephones: telephones ?? this.telephones, + faxes: faxes ?? this.faxes, + addresses: addresses ?? this.addresses, + attachments: attachments ?? this.attachments, + suppPersons: suppPersons ?? this.suppPersons, + suppTCodes: suppTCodes ?? this.suppTCodes, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['suppliername'] = suppliername; + map['name'] = name; + map['website'] = website; + map['email'] = email; + map['code'] = code; + map['suppNo'] = suppNo; + map['suppStatusId'] = suppStatusId; + map['cityId'] = cityId; + map['person'] = person; + map['comment'] = comment; + map['zipcode'] = zipcode; + map['contact'] = contact; + if (telephones != null) { + map['telephones'] = telephones.map((v) => v.toJson()).toList(); + } + if (faxes != null) { + map['faxes'] = faxes.map((v) => v.toJson()).toList(); + } + if (addresses != null) { + map['addresses'] = addresses.map((v) => v.toJson()).toList(); + } + if (attachments != null) { + map['attachments'] = attachments.map((v) => v.toJson()).toList(); + } + if (suppPersons != null) { + map['suppPersons'] = suppPersons.map((v) => v.toJson()).toList(); + } + if (suppTCodes != null) { + map['suppTCodes'] = suppTCodes.map((v) => v.toJson()).toList(); + } + return map; + } +} + +class SuppTCodes { + SuppTCodes({ + this.id, + this.supplierId, + this.codeTypeId, + this.codeValue, + }); + + SuppTCodes.fromJson(dynamic json) { + id = json['id']; + supplierId = json['supplierId']; + codeTypeId = json['codeTypeId']; + codeValue = json['codeValue']; + } + + num id; + num supplierId; + num codeTypeId; + String codeValue; + + SuppTCodes copyWith({ + num id, + num supplierId, + num codeTypeId, + String codeValue, + }) => + SuppTCodes( + id: id ?? this.id ?? 0, + supplierId: supplierId ?? this.supplierId, + codeTypeId: codeTypeId ?? this.codeTypeId, + codeValue: codeValue ?? this.codeValue, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['supplierId'] = supplierId; + map['codeTypeId'] = codeTypeId; + map['codeValue'] = codeValue; + return map; + } +} + +class SuppPersons { + SuppPersons({ + this.id, + this.supplierId, + this.personName, + this.personRoleId, + this.contact, + this.externalEngCode, + this.email, + }); + + SuppPersons.fromJson(dynamic json) { + id = json['id']; + supplierId = json['supplierId']; + personName = json['personName']; + personRoleId = json['personRoleId']; + contact = json['contact']; + externalEngCode = json['externalEngCode']; + email = json['email']; + } + + num id; + num supplierId; + String personName; + num personRoleId; + String contact; + String externalEngCode; + String email; + + SuppPersons copyWith({ + num id, + num supplierId, + String personName, + num personRoleId, + String contact, + String externalEngCode, + String email, + }) => + SuppPersons( + id: id ?? this.id, + supplierId: supplierId ?? this.supplierId, + personName: personName ?? this.personName, + personRoleId: personRoleId ?? this.personRoleId, + contact: contact ?? this.contact, + externalEngCode: externalEngCode ?? this.externalEngCode, + email: email ?? this.email, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['supplierId'] = supplierId; + map['personName'] = personName; + map['personRoleId'] = personRoleId; + map['contact'] = contact; + map['externalEngCode'] = externalEngCode; + map['email'] = email; + return map; + } +} + +class Attachments { + Attachments({ + this.id, + this.supplierId, + this.attachmentName, + this.attachmentURL, + }); + + Attachments.fromJson(dynamic json) { + id = json['id']; + supplierId = json['supplierId']; + attachmentName = json['attachmentName']; + attachmentURL = json['attachmentURL']; + } + + num id; + num supplierId; + String attachmentName; + String attachmentURL; + + Attachments copyWith({ + num id, + num supplierId, + String attachmentName, + String attachmentURL, + }) => + Attachments( + id: id ?? this.id, + supplierId: supplierId ?? this.supplierId, + attachmentName: attachmentName ?? this.attachmentName, + attachmentURL: attachmentURL ?? this.attachmentURL, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['supplierId'] = supplierId; + map['attachmentName'] = attachmentName; + map['attachmentURL'] = attachmentURL; + return map; + } +} + +class Addresses { + Addresses({ + this.id, + this.supplierId, + this.address, + }); + + Addresses.fromJson(dynamic json) { + id = json['id']; + supplierId = json['supplierId']; + address = json['address']; + } + + num id; + num supplierId; + String address; + + Addresses copyWith({ + num id, + num supplierId, + String address, + }) => + Addresses( + id: id ?? this.id, + supplierId: supplierId ?? this.supplierId, + address: address ?? this.address, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['supplierId'] = supplierId; + map['address'] = address; + return map; + } +} + +class Faxes { + Faxes({ + this.id, + this.supplierId, + this.fax, + }); + + Faxes.fromJson(dynamic json) { + id = json['id']; + supplierId = json['supplierId']; + fax = json['fax']; + } + + num id; + num supplierId; + String fax; + + Faxes copyWith({ + num id, + num supplierId, + String fax, + }) => + Faxes( + id: id ?? this.id, + supplierId: supplierId ?? this.supplierId, + fax: fax ?? this.fax, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['supplierId'] = supplierId; + map['fax'] = fax; + return map; + } +} + +class Telephones { + Telephones({ + this.id, + this.supplierId, + this.telephone, + }); + + Telephones.fromJson(dynamic json) { + id = json['id']; + supplierId = json['supplierId']; + telephone = json['telephone']; + } + + num id; + num supplierId; + String telephone; + + Telephones copyWith({ + num id, + num supplierId, + String telephone, + }) => + Telephones( + id: id ?? this.id, + supplierId: supplierId ?? this.supplierId, + telephone: telephone ?? this.telephone, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['supplierId'] = supplierId; + map['telephone'] = telephone; + return map; + } +} + +class AttachmentsWorkOrder { + AttachmentsWorkOrder({ + this.id, + this.name, + }); + + AttachmentsWorkOrder.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + } + + num id; + String name; + + AttachmentsWorkOrder copyWith({ + num id, + String name, + }) => + AttachmentsWorkOrder( + id: id ?? this.id, + name: name ?? this.name, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + return map; + } +} + +class SparePartsWorkOrders { + SparePartsWorkOrders({ + this.id, + this.sparePart, + this.qty, + this.returnQty, + this.installQty, + }); + + SparePartsWorkOrders.fromJson(dynamic json) { + id = json['id']; + sparePart = json['sparePart'] != null ? SparePart.fromJson(json['sparePart']) : null; + qty = json['qty']; + returnQty = json['returnQty']; + installQty = json['installQty']; + } + + num id; + SparePart sparePart; + num qty; + num returnQty; + num installQty; + + SparePartsWorkOrders copyWith({ + num id, + SparePart sparePart, + num qty, + num returnQty, + num installQty, + }) => + SparePartsWorkOrders( + id: id ?? this.id, + sparePart: sparePart ?? this.sparePart, + qty: qty ?? this.qty, + returnQty: returnQty ?? this.returnQty, + installQty: installQty ?? this.installQty, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + if (sparePart != null) { + map['sparePart'] = sparePart.toJson(); + } + map['qty'] = qty; + map['returnQty'] = returnQty; + map['installQty'] = installQty; + return map; + } +} + +class SparePart { + SparePart({ + this.id, + this.partNo, + this.partName, + }); + + SparePart.fromJson(dynamic json) { + id = json['id']; + partNo = json['partNo']; + partName = json['partName']; + } + + num id; + String partNo; + String partName; + + SparePart copyWith({ + num id, + String partNo, + String partName, + }) => + SparePart( + id: id ?? this.id, + partNo: partNo ?? this.partNo, + partName: partName ?? this.partName, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['partNo'] = partNo; + map['partName'] = partName; + return map; + } +} + +class ContactPersonWorkOrders { + ContactPersonWorkOrders({ + this.id, + this.employeeCode, + this.name, + this.telephone, + this.job, + this.email, + this.land, + this.contactUserId, + }); + + ContactPersonWorkOrders.fromJson(dynamic json) { + id = json['id']; + employeeCode = json['employeeCode']; + name = json['name']; + telephone = json['telephone']; + job = json['job']; + email = json['email']; + land = json['land']; + contactUserId = json['contactUserId']; + } + + num id; + String employeeCode; + String name; + String telephone; + String job; + String email; + String land; + String contactUserId; + + ContactPersonWorkOrders copyWith({ + num id, + String employeeCode, + String name, + String telephone, + String job, + String email, + String land, + String contactUserId, + }) => + ContactPersonWorkOrders( + id: id ?? this.id, + employeeCode: employeeCode ?? this.employeeCode, + name: name ?? this.name, + telephone: telephone ?? this.telephone, + job: job ?? this.job, + email: email ?? this.email, + land: land ?? this.land, + contactUserId: contactUserId ?? this.contactUserId, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['employeeCode'] = employeeCode; + map['name'] = name; + map['telephone'] = telephone; + map['job'] = job; + map['email'] = email; + map['land'] = land; + map['contactUserId'] = contactUserId; + return map; + } +} + +class AssistantEmployees { + AssistantEmployees({ + this.id, + this.user, + }); + + AssistantEmployees.fromJson(dynamic json) { + id = json['id']; + user = json['user'] != null ? UserModel.fromJson(json['user']) : UserModel(name: json['userName'], id: json['userId']); + } + + num id; + UserModel user; + + AssistantEmployees copyWith({ + num id, + UserModel user, + }) => + AssistantEmployees( + id: id ?? this.id, + user: user ?? this.user, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + if (user != null) { + map['user'] = user.toJson(); + } + return map; + } +} + +class UserModel { + UserModel({ + this.id, + this.name, + }); + + UserModel.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + } + + String id; + String name; + + UserModel copyWith({ + String id, + String name, + }) => + UserModel( + id: id ?? this.id, + name: name ?? this.name, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + return map; + } +} + +class AssignedEmployee { + AssignedEmployee({ + this.id, + this.name, + }); + + AssignedEmployee.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + } + + String id; + String name; + + AssignedEmployee copyWith({ + String id, + String name, + }) => + AssignedEmployee( + id: id ?? this.id, + name: name ?? this.name, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + return map; + } +} + +class CallRequest { + CallRequest({ + this.id, + this.callNo, + this.callComments, + this.asset, + this.assignedEmployee, + this.callSiteContactPerson, + this.status, + this.callLastSituation, + this.defectType, + this.firstAction, + this.assetType, + }); + + CallRequest.fromJson(dynamic json) { + id = json['id']; + callNo = json['callNo']; + callComments = json['callComments']; + asset = json['asset'] != null ? Asset.fromJson(json['asset']) : null; + assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null; + if (json['callSiteContactPerson'] != null) { + callSiteContactPerson = []; + json['callSiteContactPerson'].forEach((v) { + callSiteContactPerson.add(CallSiteContactPerson.fromJson(v)); + }); + } + status = json['status'] != null ? Status.fromJson(json['status']) : null; + callLastSituation = json['callLastSituation'] != null ? Lookup.fromJson(json['callLastSituation']) : null; + defectType = json['defectType'] != null ? DefectType.fromJson(json['defectType']) : null; + firstAction = json['firstAction'] != null ? FirstAction.fromJson(json['firstAction']) : null; + assetType = json['assetType']; + } + + num id; + String callNo; + String callComments; + Asset asset; + AssignedEmployee assignedEmployee; + List callSiteContactPerson; + Status status; + Lookup callLastSituation; + DefectType defectType; + FirstAction firstAction; + num assetType; + + CallRequest copyWith({ + num id, + String callNo, + String callComments, + Asset asset, + AssignedEmployee assignedEmployee, + List callSiteContactPerson, + Status status, + Lookup callLastSituation, + DefectType defectType, + FirstAction firstAction, + num assetType, + }) => + CallRequest( + id: id ?? this.id, + callNo: callNo ?? this.callNo, + callComments: callComments ?? this.callComments, + asset: asset ?? this.asset, + assignedEmployee: assignedEmployee ?? this.assignedEmployee, + callSiteContactPerson: callSiteContactPerson ?? this.callSiteContactPerson, + status: status ?? this.status, + callLastSituation: callLastSituation ?? this.callLastSituation, + defectType: defectType ?? this.defectType, + firstAction: firstAction ?? this.firstAction, + assetType: assetType ?? this.assetType, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['callNo'] = callNo; + map['callComments'] = callComments; + if (asset != null) { + map['asset'] = asset.toJson(); + } + if (assignedEmployee != null) { + map['assignedEmployee'] = assignedEmployee.toJson(); + } + if (callSiteContactPerson != null) { + map['callSiteContactPerson'] = callSiteContactPerson.map((v) => v.toJson()).toList(); + } + if (status != null) { + map['status'] = status.toJson(); + } + if (callLastSituation != null) { + map['callLastSituation'] = callLastSituation.toMap(); + } + if (defectType != null) { + map['defectType'] = defectType.toJson(); + } + if (firstAction != null) { + map['firstAction'] = firstAction.toJson(); + } + map['assetType'] = assetType; + return map; + } +} + +class FirstAction { + FirstAction({ + this.id, + this.name, + this.value, + }); + + FirstAction.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + } + + num id; + String name; + num value; + + FirstAction copyWith({ + num id, + String name, + num value, + }) => + FirstAction( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + map['value'] = value; + return map; + } +} + +class DefectType { + DefectType({ + this.id, + this.name, + this.value, + }); + + DefectType.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + } + + num id; + String name; + num value; + + DefectType copyWith({ + num id, + String name, + num value, + }) => + DefectType( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + map['value'] = value; + return map; + } +} + +class Status { + Status({ + this.id, + this.name, + this.value, + }); + + Status.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + } + + num id; + String name; + num value; + + Status copyWith({ + num id, + String name, + num value, + }) => + Status( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + map['value'] = value; + return map; + } +} + +class CallSiteContactPerson { + CallSiteContactPerson({ + this.id, + this.employeeCode, + this.name, + this.telephone, + this.job, + this.email, + this.land, + this.contactUserId, + }); + + CallSiteContactPerson.fromJson(dynamic json) { + id = json['id']; + employeeCode = json['employeeCode']; + name = json['name']; + telephone = json['telephone']; + job = json['job']; + email = json['email']; + land = json['land']; + contactUserId = json['contactUserId']; + } + + num id; + String employeeCode; + String name; + String telephone; + String job; + String email; + String land; + String contactUserId; + + CallSiteContactPerson copyWith({ + num id, + String employeeCode, + String name, + String telephone, + String job, + String email, + String land, + String contactUserId, + }) => + CallSiteContactPerson( + id: id ?? this.id, + employeeCode: employeeCode ?? this.employeeCode, + name: name ?? this.name, + telephone: telephone ?? this.telephone, + job: job ?? this.job, + email: email ?? this.email, + land: land ?? this.land, + contactUserId: contactUserId ?? this.contactUserId, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['employeeCode'] = employeeCode; + map['name'] = name; + map['telephone'] = telephone; + map['job'] = job; + map['email'] = email; + map['land'] = land; + map['contactUserId'] = contactUserId; + return map; + } +} + +class Asset { + Asset({ + this.id, + this.assetSerialNo, + this.systemID, + this.assetNumber, + this.modelDefinition, + this.supplier, + this.ipAddress, + this.macAddress, + this.portNumber, + this.assetReplace, + this.oldAsset, + this.isParent, + this.parentAsset, + this.assetType, + this.site, + this.building, + this.floor, + this.department, + this.room, + this.testsDay, + this.purchasingPrice, + this.nbv, + this.currency, + this.poNo, + this.invoiceNumber, + this.invoiceDate, + this.replacementDate, + this.originDepartment, + this.originSite, + this.budgetYear, + this.lastPOPrice, + this.commissioningStatus, + this.productionDate, + this.edd, + this.technicalInspectionDate, + this.deliveryInspectionDate, + this.endUserAcceptanceDate, + this.receivingCommittee, + this.siteWarrantyMonths, + this.extendedWarrantyMonths, + this.remainderWarrantyMonths, + this.eomWarrantyMonthsNo, + this.warrantyValue, + this.warrantyEndDate, + this.warrantyContractConditions, + this.technicalGuidanceBooks, + this.comment, + this.tagCode, + }); + + Asset.fromJson(dynamic json) { + id = json['id']; + assetSerialNo = json['assetSerialNo']; + systemID = json['systemID']; + assetNumber = json['assetNumber']; + modelDefinition = json['modelDefinition'] != null ? ModelDefinition.fromJson(json['modelDefinition']) : null; + supplier = json['supplier'] != null ? Supplier.fromJson(json['supplier']) : null; + ipAddress = json['ipAddress']; + macAddress = json['macAddress']; + portNumber = json['portNumber']; + assetReplace = json['assetReplace'] != null ? AssetReplace.fromJson(json['assetReplace']) : null; + oldAsset = json['oldAsset'] != null ? OldAsset.fromJson(json['oldAsset']) : null; + isParent = json['isParent'] != null ? IsParent.fromJson(json['isParent']) : null; + parentAsset = json['parentAsset'] != null ? ParentAsset.fromJson(json['parentAsset']) : null; + assetType = json['assetType'] != null ? Lookup.fromJson(json['assetType']) : null; + site = json['site'] != null ? Site.fromJson(json['site']) : null; + building = json['building'] != null ? Building.fromJson(json['building']) : null; + floor = json['floor'] != null ? Floor.fromJson(json['floor']) : null; + department = json['department'] != null ? Department.fromJson(json['department']) : null; + room = json['room']; + testsDay = json['testsDay']; + purchasingPrice = json['purchasingPrice']; + nbv = json['nbv']; + currency = json['currency'] != null ? Currency.fromJson(json['currency']) : null; + poNo = json['poNo']; + invoiceNumber = json['invoiceNumber']; + invoiceDate = json['invoiceDate']; + replacementDate = json['replacementDate']; + originDepartment = json['originDepartment'] != null ? OriginDepartment.fromJson(json['originDepartment']) : null; + originSite = json['originSite'] != null ? OriginSite.fromJson(json['originSite']) : null; + budgetYear = json['budgetYear']; + lastPOPrice = json['lastPOPrice']; + commissioningStatus = json['commissioningStatus'] != null ? CommissioningStatus.fromJson(json['commissioningStatus']) : null; + productionDate = json['productionDate']; + edd = json['edd']; + technicalInspectionDate = json['technicalInspectionDate']; + deliveryInspectionDate = json['deliveryInspectionDate']; + endUserAcceptanceDate = json['endUserAcceptanceDate']; + receivingCommittee = json['receivingCommittee']; + siteWarrantyMonths = json['siteWarrantyMonths'] != null ? SiteWarrantyMonths.fromJson(json['siteWarrantyMonths']) : null; + extendedWarrantyMonths = json['extendedWarrantyMonths'] != null ? ExtendedWarrantyMonths.fromJson(json['extendedWarrantyMonths']) : null; + remainderWarrantyMonths = json['remainderWarrantyMonths'] != null ? RemainderWarrantyMonths.fromJson(json['remainderWarrantyMonths']) : null; + eomWarrantyMonthsNo = json['eomWarrantyMonthsNo']; + warrantyValue = json['warrantyValue']; + warrantyEndDate = json['warrantyEndDate']; + warrantyContractConditions = json['warrantyContractConditions']; + if (json['technicalGuidanceBooks'] != null) { + technicalGuidanceBooks = []; + json['technicalGuidanceBooks'].forEach((v) { + technicalGuidanceBooks.add(TechnicalGuidanceBooks.fromJson(v)); + }); + } + comment = json['comment']; + tagCode = json['tagCode']; + } + + num id; + String assetSerialNo; + String systemID; + String assetNumber; + ModelDefinition modelDefinition; + Supplier supplier; + String ipAddress; + String macAddress; + String portNumber; + AssetReplace assetReplace; + OldAsset oldAsset; + IsParent isParent; + ParentAsset parentAsset; + Lookup assetType; + Site site; + Building building; + Floor floor; + Department department; + String room; + num testsDay; + num purchasingPrice; + String nbv; + Currency currency; + String poNo; + String invoiceNumber; + String invoiceDate; + String replacementDate; + OriginDepartment originDepartment; + OriginSite originSite; + num budgetYear; + num lastPOPrice; + CommissioningStatus commissioningStatus; + String productionDate; + String edd; + String technicalInspectionDate; + String deliveryInspectionDate; + String endUserAcceptanceDate; + String receivingCommittee; + SiteWarrantyMonths siteWarrantyMonths; + ExtendedWarrantyMonths extendedWarrantyMonths; + RemainderWarrantyMonths remainderWarrantyMonths; + num eomWarrantyMonthsNo; + num warrantyValue; + String warrantyEndDate; + String warrantyContractConditions; + List technicalGuidanceBooks; + String comment; + String tagCode; + + Asset copyWith({ + num id, + String assetSerialNo, + String systemID, + String assetNumber, + ModelDefinition modelDefinition, + SupplierModel supplier, + String ipAddress, + String macAddress, + String portNumber, + AssetReplace assetReplace, + OldAsset oldAsset, + IsParent isParent, + ParentAsset parentAsset, + Lookup assetType, + Site site, + Building building, + Floor floor, + Department department, + String room, + num testsDay, + num purchasingPrice, + String nbv, + Currency currency, + String poNo, + String invoiceNumber, + String invoiceDate, + String replacementDate, + OriginDepartment originDepartment, + OriginSite originSite, + num budgetYear, + num lastPOPrice, + CommissioningStatus commissioningStatus, + String productionDate, + String edd, + String technicalInspectionDate, + String deliveryInspectionDate, + String endUserAcceptanceDate, + String receivingCommittee, + SiteWarrantyMonths siteWarrantyMonths, + ExtendedWarrantyMonths extendedWarrantyMonths, + RemainderWarrantyMonths remainderWarrantyMonths, + num eomWarrantyMonthsNo, + num warrantyValue, + String warrantyEndDate, + String warrantyContractConditions, + List technicalGuidanceBooks, + String comment, + String tagCode, + }) => + Asset( + id: id ?? this.id, + assetSerialNo: assetSerialNo ?? this.assetSerialNo, + systemID: systemID ?? this.systemID, + assetNumber: assetNumber ?? this.assetNumber, + modelDefinition: modelDefinition ?? this.modelDefinition, + supplier: supplier ?? this.supplier, + ipAddress: ipAddress ?? this.ipAddress, + macAddress: macAddress ?? this.macAddress, + portNumber: portNumber ?? this.portNumber, + assetReplace: assetReplace ?? this.assetReplace, + oldAsset: oldAsset ?? this.oldAsset, + isParent: isParent ?? this.isParent, + parentAsset: parentAsset ?? this.parentAsset, + assetType: assetType ?? this.assetType, + site: site ?? this.site, + building: building ?? this.building, + floor: floor ?? this.floor, + department: department ?? this.department, + room: room ?? this.room, + testsDay: testsDay ?? this.testsDay, + purchasingPrice: purchasingPrice ?? this.purchasingPrice, + nbv: nbv ?? this.nbv, + currency: currency ?? this.currency, + poNo: poNo ?? this.poNo, + invoiceNumber: invoiceNumber ?? this.invoiceNumber, + invoiceDate: invoiceDate ?? this.invoiceDate, + replacementDate: replacementDate ?? this.replacementDate, + originDepartment: originDepartment ?? this.originDepartment, + originSite: originSite ?? this.originSite, + budgetYear: budgetYear ?? this.budgetYear, + lastPOPrice: lastPOPrice ?? this.lastPOPrice, + commissioningStatus: commissioningStatus ?? this.commissioningStatus, + productionDate: productionDate ?? this.productionDate, + edd: edd ?? this.edd, + technicalInspectionDate: technicalInspectionDate ?? this.technicalInspectionDate, + deliveryInspectionDate: deliveryInspectionDate ?? this.deliveryInspectionDate, + endUserAcceptanceDate: endUserAcceptanceDate ?? this.endUserAcceptanceDate, + receivingCommittee: receivingCommittee ?? this.receivingCommittee, + siteWarrantyMonths: siteWarrantyMonths ?? this.siteWarrantyMonths, + extendedWarrantyMonths: extendedWarrantyMonths ?? this.extendedWarrantyMonths, + remainderWarrantyMonths: remainderWarrantyMonths ?? this.remainderWarrantyMonths, + eomWarrantyMonthsNo: eomWarrantyMonthsNo ?? this.eomWarrantyMonthsNo, + warrantyValue: warrantyValue ?? this.warrantyValue, + warrantyEndDate: warrantyEndDate ?? this.warrantyEndDate, + warrantyContractConditions: warrantyContractConditions ?? this.warrantyContractConditions, + technicalGuidanceBooks: technicalGuidanceBooks ?? this.technicalGuidanceBooks, + comment: comment ?? this.comment, + tagCode: tagCode ?? this.tagCode, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['assetSerialNo'] = assetSerialNo; + map['systemID'] = systemID; + map['assetNumber'] = assetNumber; + if (modelDefinition != null) { + map['modelDefinition'] = modelDefinition.toJson(); + } + map['supplier'] = supplier?.toJson(); + + map['ipAddress'] = ipAddress; + map['macAddress'] = macAddress; + map['portNumber'] = portNumber; + if (assetReplace != null) { + map['assetReplace'] = assetReplace.toJson(); + } + if (oldAsset != null) { + map['oldAsset'] = oldAsset.toJson(); + } + if (isParent != null) { + map['isParent'] = isParent.toJson(); + } + if (parentAsset != null) { + map['parentAsset'] = parentAsset.toJson(); + } + + map['assetType'] = assetType?.toMap(); + print("supplier : ${supplier?.toJson()}"); + print("supplier 2 : ${map['supplier']}"); + print("asset type : ${assetType?.toMap()}"); + print("asset type 2: ${map['assetType']}"); + if (site != null) { + map['site'] = site.toJson(); + } + if (building != null) { + map['building'] = building.toJson(); + } + if (floor != null) { + map['floor'] = floor.toJson(); + } + if (department != null) { + map['department'] = department.toJson(); + } + map['room'] = room; + map['testsDay'] = testsDay; + map['purchasingPrice'] = purchasingPrice; + map['nbv'] = nbv; + if (currency != null) { + map['currency'] = currency.toJson(); + } + map['poNo'] = poNo; + map['invoiceNumber'] = invoiceNumber; + map['invoiceDate'] = invoiceDate; + map['replacementDate'] = replacementDate; + if (originDepartment != null) { + map['originDepartment'] = originDepartment.toJson(); + } + if (originSite != null) { + map['originSite'] = originSite.toJson(); + } + map['budgetYear'] = budgetYear; + map['lastPOPrice'] = lastPOPrice; + if (commissioningStatus != null) { + map['commissioningStatus'] = commissioningStatus.toJson(); + } + map['productionDate'] = productionDate; + map['edd'] = edd; + map['technicalInspectionDate'] = technicalInspectionDate; + map['deliveryInspectionDate'] = deliveryInspectionDate; + map['endUserAcceptanceDate'] = endUserAcceptanceDate; + map['receivingCommittee'] = receivingCommittee; + if (siteWarrantyMonths != null) { + map['siteWarrantyMonths'] = siteWarrantyMonths.toJson(); + } + if (extendedWarrantyMonths != null) { + map['extendedWarrantyMonths'] = extendedWarrantyMonths.toJson(); + } + if (remainderWarrantyMonths != null) { + map['remainderWarrantyMonths'] = remainderWarrantyMonths.toJson(); + } + map['eomWarrantyMonthsNo'] = eomWarrantyMonthsNo; + map['warrantyValue'] = warrantyValue; + map['warrantyEndDate'] = warrantyEndDate; + map['warrantyContractConditions'] = warrantyContractConditions; + if (technicalGuidanceBooks != null) { + map['technicalGuidanceBooks'] = technicalGuidanceBooks.map((v) => v.toJson()).toList(); + } + map['comment'] = comment; + map['tagCode'] = tagCode; + return map; + } +} + +class TechnicalGuidanceBooks { + TechnicalGuidanceBooks({ + this.id, + this.guidanceBook, + }); + + TechnicalGuidanceBooks.fromJson(dynamic json) { + id = json['id']; + guidanceBook = json['guidanceBook'] != null ? GuidanceBook.fromJson(json['guidanceBook']) : null; + } + + num id; + GuidanceBook guidanceBook; + + TechnicalGuidanceBooks copyWith({ + num id, + GuidanceBook guidanceBook, + }) => + TechnicalGuidanceBooks( + id: id ?? this.id, + guidanceBook: guidanceBook ?? this.guidanceBook, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + if (guidanceBook != null) { + map['guidanceBook'] = guidanceBook.toJson(); + } + return map; + } +} + +class GuidanceBook { + GuidanceBook({ + this.id, + this.name, + this.value, + }); + + GuidanceBook.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + } + + num id; + String name; + num value; + + GuidanceBook copyWith({ + num id, + String name, + num value, + }) => + GuidanceBook( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + map['value'] = value; + return map; + } +} + +class RemainderWarrantyMonths { + RemainderWarrantyMonths({ + this.id, + this.name, + this.value, + }); + + RemainderWarrantyMonths.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + } + + num id; + String name; + num value; + + RemainderWarrantyMonths copyWith({ + num id, + String name, + num value, + }) => + RemainderWarrantyMonths( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + map['value'] = value; + return map; + } +} + +class ExtendedWarrantyMonths { + ExtendedWarrantyMonths({ + this.id, + this.name, + this.value, + }); + + ExtendedWarrantyMonths.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + } + + num id; + String name; + num value; + + ExtendedWarrantyMonths copyWith({ + num id, + String name, + num value, + }) => + ExtendedWarrantyMonths( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + map['value'] = value; + return map; + } +} + +class SiteWarrantyMonths { + SiteWarrantyMonths({ + this.id, + this.name, + this.value, + }); + + SiteWarrantyMonths.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + } + + num id; + String name; + num value; + + SiteWarrantyMonths copyWith({ + num id, + String name, + num value, + }) => + SiteWarrantyMonths( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + map['value'] = value; + return map; + } +} + +class CommissioningStatus { + CommissioningStatus({ + this.id, + this.name, + this.value, + }); + + CommissioningStatus.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + } + + num id; + String name; + num value; + + CommissioningStatus copyWith({ + num id, + String name, + num value, + }) => + CommissioningStatus( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + map['value'] = value; + return map; + } +} + +class OriginSite { + OriginSite({ + this.id, + this.customerCode, + this.custName, + this.buildings, + }); + + OriginSite.fromJson(dynamic json) { + id = json['id']; + customerCode = json['customerCode']; + custName = json['custName']; + if (json['buildings'] != null) { + buildings = []; + json['buildings'].forEach((v) { + buildings.add(Buildings.fromJson(v)); + }); + } + } + + num id; + num customerCode; + String custName; + List buildings; + + OriginSite copyWith({ + num id, + num customerCode, + String custName, + List buildings, + }) => + OriginSite( + id: id ?? this.id, + customerCode: customerCode ?? this.customerCode, + custName: custName ?? this.custName, + buildings: buildings ?? this.buildings, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['customerCode'] = customerCode; + map['custName'] = custName; + if (buildings != null) { + map['buildings'] = buildings.map((v) => v.toJson()).toList(); + } + return map; + } +} + +class Buildings { + Buildings({ + this.id, + this.name, + this.value, + this.floors, + }); + + Buildings.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + if (json['floors'] != null) { + floors = []; + json['floors'].forEach((v) { + floors.add(Floors.fromJson(v)); + }); + } + } + + num id; + String name; + num value; + List floors; + + Buildings copyWith({ + num id, + String name, + num value, + List floors, + }) => + Buildings( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + floors: floors ?? this.floors, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + map['value'] = value; + if (floors != null) { + map['floors'] = floors.map((v) => v.toJson()).toList(); + } + return map; + } +} + +class Floors { + Floors({ + this.id, + this.name, + this.value, + this.departments, + }); + + Floors.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + if (json['departments'] != null) { + departments = []; + json['departments'].forEach((v) { + departments.add(Departments.fromJson(v)); + }); + } + } + + num id; + String name; + num value; + List departments; + + Floors copyWith({ + num id, + String name, + num value, + List departments, + }) => + Floors( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + departments: departments ?? this.departments, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + map['value'] = value; + if (departments != null) { + map['departments'] = departments.map((v) => v.toJson()).toList(); + } + return map; + } +} + +class Departments { + Departments({ + this.id, + this.name, + }); + + Departments.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + } + + num id; + String name; + + Departments copyWith({ + num id, + String name, + }) => + Departments( + id: id ?? this.id, + name: name ?? this.name, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + return map; + } +} + +class OriginDepartment { + OriginDepartment({ + this.id, + this.departmentName, + this.departmentCode, + this.ntCode, + }); + + OriginDepartment.fromJson(dynamic json) { + id = json['id']; + departmentName = json['departmentName']; + departmentCode = json['departmentCode']; + ntCode = json['ntCode']; + } + + num id; + String departmentName; + String departmentCode; + String ntCode; + + OriginDepartment copyWith({ + num id, + String departmentName, + String departmentCode, + String ntCode, + }) => + OriginDepartment( + id: id ?? this.id ?? 0, + departmentName: departmentName ?? this.departmentName, + departmentCode: departmentCode ?? this.departmentCode, + ntCode: ntCode ?? this.ntCode, + ); + + Map toJson() { + final map = {}; + map['id'] = id; + map['departmentName'] = departmentName; + map['departmentCode'] = departmentCode; + map['ntCode'] = ntCode; + return map; + } +} + +class Currency { + Currency({ + this.id, + this.name, + this.value, + }); + + Currency.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + } + + num id; + String name; + num value; + + Currency copyWith({ + num id, + String name, + num value, + }) => + Currency( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + map['value'] = value; + return map; + } +} + +class Department { + Department({ + this.id, + this.departmentName, + this.departmentCode, + this.ntCode, + }); + + Department.fromJson(dynamic json) { + id = json['id']; + departmentName = json['departmentName']; + departmentCode = json['departmentCode']; + ntCode = json['ntCode']; + } + + num id; + String departmentName; + String departmentCode; + String ntCode; + + Department copyWith({ + num id, + String departmentName, + String departmentCode, + String ntCode, + }) => + Department( + id: id ?? this.id, + departmentName: departmentName ?? this.departmentName, + departmentCode: departmentCode ?? this.departmentCode, + ntCode: ntCode ?? this.ntCode, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['departmentName'] = departmentName; + map['departmentCode'] = departmentCode; + map['ntCode'] = ntCode; + return map; + } +} + +class Floor { + Floor({ + this.id, + this.name, + this.value, + }); + + Floor.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + } + + num id; + String name; + num value; + + Floor copyWith({ + num id, + String name, + num value, + }) => + Floor( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + map['value'] = value; + return map; + } +} + +class Building { + Building({ + this.id, + this.name, + this.value, + }); + + Building.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + } + + num id; + String name; + num value; + + Building copyWith({ + num id, + String name, + num value, + }) => + Building( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + map['value'] = value; + return map; + } +} + +class Site { + Site({ + this.id, + this.customerCode, + this.custName, + this.buildings, + }); + + Site.fromJson(dynamic json) { + id = json['id']; + customerCode = json['customerCode']; + custName = json['custName']; + if (json['buildings'] != null) { + buildings = []; + json['buildings'].forEach((v) { + buildings.add(Buildings.fromJson(v)); + }); + } + } + + num id; + num customerCode; + String custName; + List buildings; + + Site copyWith({ + num id, + num customerCode, + String custName, + List buildings, + }) => + Site( + id: id ?? this.id, + customerCode: customerCode ?? this.customerCode, + custName: custName ?? this.custName, + buildings: buildings ?? this.buildings, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['customerCode'] = customerCode; + map['custName'] = custName; + if (buildings != null) { + map['buildings'] = buildings.map((v) => v.toJson()).toList(); + } + return map; + } +} + +class ParentAsset { + ParentAsset({ + this.id, + this.assetSerialNo, + this.assetNumber, + this.tagCode, + this.systemId, + }); + + ParentAsset.fromJson(dynamic json) { + id = json['id']; + assetSerialNo = json['assetSerialNo']; + assetNumber = json['assetNumber']; + tagCode = json['tagCode']; + systemId = json['systemId']; + } + + num id; + String assetSerialNo; + String assetNumber; + String tagCode; + String systemId; + + ParentAsset copyWith({ + num id, + String assetSerialNo, + String assetNumber, + String tagCode, + String systemId, + }) => + ParentAsset( + id: id ?? this.id, + assetSerialNo: assetSerialNo ?? this.assetSerialNo, + assetNumber: assetNumber ?? this.assetNumber, + tagCode: tagCode ?? this.tagCode, + systemId: systemId ?? this.systemId, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['assetSerialNo'] = assetSerialNo; + map['assetNumber'] = assetNumber; + map['tagCode'] = tagCode; + map['systemId'] = systemId; + return map; + } +} + +class IsParent { + IsParent({ + this.id, + this.name, + this.value, + }); + + IsParent.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + } + + num id; + String name; + num value; + + IsParent copyWith({ + num id, + String name, + num value, + }) => + IsParent( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + map['value'] = value; + return map; + } +} + +class OldAsset { + OldAsset({ + this.id, + this.assetSerialNo, + this.assetNumber, + this.tagCode, + this.systemId, + }); + + OldAsset.fromJson(dynamic json) { + id = json['id']; + assetSerialNo = json['assetSerialNo']; + assetNumber = json['assetNumber']; + tagCode = json['tagCode']; + systemId = json['systemId']; + } + + num id; + String assetSerialNo; + String assetNumber; + String tagCode; + String systemId; + + OldAsset copyWith({ + num id, + String assetSerialNo, + String assetNumber, + String tagCode, + String systemId, + }) => + OldAsset( + id: id ?? this.id ?? 0, + assetSerialNo: assetSerialNo ?? this.assetSerialNo, + assetNumber: assetNumber ?? this.assetNumber, + tagCode: tagCode ?? this.tagCode, + systemId: systemId ?? this.systemId, + ); + + Map toJson() { + final map = {}; + map['id'] = id; + map['assetSerialNo'] = assetSerialNo; + map['assetNumber'] = assetNumber; + map['tagCode'] = tagCode; + map['systemId'] = systemId; + return map; + } +} + +class AssetReplace { + AssetReplace({ + this.id, + this.name, + this.value, + }); + + AssetReplace.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + } + + num id; + String name; + num value; + + AssetReplace copyWith({ + num id, + String name, + num value, + }) => + AssetReplace( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['name'] = name; + map['value'] = value; + return map; + } +} + +class Supplier { + Supplier({ + this.id, + this.suppliername, + }); + + Supplier.fromJson(dynamic json) { + id = json['id']; + suppliername = json['suppliername']; + } + + num id; + String suppliername; + + SupplierModel copyWith({ + num id, + String suppliername, + }) => + SupplierModel( + id: id ?? this.id, + suppliername: suppliername ?? this.suppliername, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['suppliername'] = suppliername; + return map; + } +} + +class ModelDefinition { + ModelDefinition({ + this.id, + this.assetName, + this.modelDefCode, + this.modelName, + this.manufacturerId, + this.manufacturerName, + this.supplierName, + this.replacementDate, + this.essentialEquipement, + this.businessCritical, + this.lifeSpan, + this.modelDefRelatedDefects, + this.suppliers, + }); + + ModelDefinition.fromJson(dynamic json) { + id = json['id']; + assetName = json['assetName']; + modelDefCode = json['modelDefCode']; + modelName = json['modelName']; + manufacturerId = json['manufacturerId']; + manufacturerName = json['manufacturerName']; + supplierName = json['supplierName']; + replacementDate = json['replacementDate']; + essentialEquipement = json['essentialEquipement']; + businessCritical = json['businessCritical']; + lifeSpan = json['lifeSpan']; + if (json['modelDefRelatedDefects'] != null) { + modelDefRelatedDefects = []; + json['modelDefRelatedDefects'].forEach((v) { + modelDefRelatedDefects.add(ModelDefRelatedDefects.fromJson(v)); + }); + } + if (json['suppliers'] != null) { + suppliers = []; + json['suppliers'].forEach((v) { + suppliers.add(Suppliers.fromJson(v)); + }); + } + } + + num id; + String assetName; + String modelDefCode; + String modelName; + num manufacturerId; + String manufacturerName; + String supplierName; + String replacementDate; + String essentialEquipement; + String businessCritical; + num lifeSpan; + List modelDefRelatedDefects; + List suppliers; + + ModelDefinition copyWith({ + num id, + String assetName, + String modelDefCode, + String modelName, + num manufacturerId, + String manufacturerName, + String supplierName, + String replacementDate, + String essentialEquipement, + String businessCritical, + num lifeSpan, + List modelDefRelatedDefects, + List suppliers, + }) => + ModelDefinition( + id: id ?? this.id, + assetName: assetName ?? this.assetName, + modelDefCode: modelDefCode ?? this.modelDefCode, + modelName: modelName ?? this.modelName, + manufacturerId: manufacturerId ?? this.manufacturerId, + manufacturerName: manufacturerName ?? this.manufacturerName, + supplierName: supplierName ?? this.supplierName, + replacementDate: replacementDate ?? this.replacementDate, + essentialEquipement: essentialEquipement ?? this.essentialEquipement, + businessCritical: businessCritical ?? this.businessCritical, + lifeSpan: lifeSpan ?? this.lifeSpan, + modelDefRelatedDefects: modelDefRelatedDefects ?? this.modelDefRelatedDefects, + suppliers: suppliers ?? this.suppliers, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['assetName'] = assetName; + map['modelDefCode'] = modelDefCode; + map['modelName'] = modelName; + map['manufacturerId'] = manufacturerId; + map['manufacturerName'] = manufacturerName; + map['supplierName'] = supplierName; + map['replacementDate'] = replacementDate; + map['essentialEquipement'] = essentialEquipement; + map['businessCritical'] = businessCritical; + map['lifeSpan'] = lifeSpan; + if (modelDefRelatedDefects != null) { + map['modelDefRelatedDefects'] = modelDefRelatedDefects.map((v) => v.toJson()).toList(); + } + if (suppliers != null) { + map['suppliers'] = suppliers.map((v) => v.toJson()).toList(); + } + return map; + } +} + +class Suppliers { + Suppliers({ + this.id, + this.suppliername, + }); + + Suppliers.fromJson(dynamic json) { + id = json['id']; + suppliername = json['suppliername']; + } + + num id; + String suppliername; + + Suppliers copyWith({ + num id, + String suppliername, + }) => + Suppliers( + id: id ?? this.id, + suppliername: suppliername ?? this.suppliername, + ); + + Map toJson() { + final map = {}; + map['id'] = id ?? 0; + map['suppliername'] = suppliername; + return map; + } +} + +class ModelDefRelatedDefects { + ModelDefRelatedDefects({ + this.id, + this.defectName, + this.workPerformed, + this.estimatedTime, + }); + + ModelDefRelatedDefects.fromJson(dynamic json) { + id = json['id']; + defectName = json['defectName']; + workPerformed = json['workPerformed']; + estimatedTime = json['estimatedTime']; + } + + num id; + String defectName; + String workPerformed; + String estimatedTime; + + ModelDefRelatedDefects copyWith({ + num id, + String defectName, + String workPerformed, + String estimatedTime, + }) => + ModelDefRelatedDefects( + id: id ?? this.id ?? 0, + defectName: defectName ?? this.defectName, + workPerformed: workPerformed ?? this.workPerformed, + estimatedTime: estimatedTime ?? this.estimatedTime, + ); + + Map toJson() { + final map = {}; + map['id'] = id; + map['defectName'] = defectName; + map['workPerformed'] = workPerformed; + map['estimatedTime'] = estimatedTime; + return map; + } +} diff --git a/lib/models/service_request/service_request.dart b/lib/models/service_request/service_request.dart index edf66852..68a55eb8 100644 --- a/lib/models/service_request/service_request.dart +++ b/lib/models/service_request/service_request.dart @@ -1,22 +1,28 @@ +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/device/device.dart'; import 'package:test_sa/models/lookup.dart'; -class ServiceRequest{ +class ServiceRequest { String id; String requestCode; String deviceSerialNumber; - String deviceId; + int deviceId; String deviceArName; String deviceEnName; List devicePhotos; - String maintenanceIssue; + String callComments; String hospitalName; - String hospitalId; + int hospitalId; String departmentName; String engineerName; + String engineerId; String date; String audio; int statusValue; + int statusId; String statusLabel; + String reviewComment; + String comments; bool viewReport; String engineerMobile; @@ -26,10 +32,15 @@ class ServiceRequest{ String visitDate; DateTime nextVisitDate; String jobSheetNumber; - String reportID; + int reportID; String deviceNumber; Lookup priority; Lookup defectType; + Lookup type; + Lookup requestedThrough; + Lookup firstAction; + Lookup loanAvailability; + Device device; ServiceRequest({ this.id, @@ -41,14 +52,15 @@ class ServiceRequest{ this.devicePhotos, this.hospitalId, this.deviceSerialNumber, - this.maintenanceIssue, + this.callComments, this.statusLabel, this.statusValue, + this.statusId, this.departmentName, this.deviceId, this.audio, this.engineerName, - + this.engineerId, this.viewReport = false, this.deviceModel, this.engineerMobile, @@ -61,42 +73,60 @@ class ServiceRequest{ this.defectType, this.priority, this.deviceNumber, - + this.type, + this.requestedThrough, + this.device, + this.reviewComment, + this.comments, + this.loanAvailability, + this.firstAction, }); - factory ServiceRequest.fromJson(Map parsedJson){ + factory ServiceRequest.fromJson(Map parsedJson) { + List images = []; + if (parsedJson["attachmentsCallRequest"] != null) if (parsedJson["attachmentsCallRequest"] is List) { + List list = parsedJson["attachmentsCallRequest"]; + images = list.map((e) => URLs.getFileUrl(e["attachmentsCallRequest"])).toList(); + } return ServiceRequest( - id: parsedJson["nid"], - requestCode: parsedJson["call_id"] ?? parsedJson["jobcode"] , - hospitalName: parsedJson["call_client"], - deviceNumber: parsedJson["device_no"], - deviceId: parsedJson["deviceid"], - audio: parsedJson["audio"] ?? "", - deviceArName: parsedJson["equipment_arabic_name"] == false - ? "No Name found" : parsedJson["equipment_arabic_name"], - deviceEnName: parsedJson["equipment_english_name"] == false - ? "No Name found" : parsedJson["equipment_english_name"], - devicePhotos: List.from(parsedJson["image"]), - deviceSerialNumber: parsedJson["call_sn"], - date: parsedJson["call_data"], - maintenanceIssue: parsedJson["call_complaint"] ?? parsedJson["complaint"], - statusLabel: parsedJson["status_value"], - statusValue: int.tryParse(parsedJson["status"]??"-1"), - departmentName: parsedJson["department_name"], - engineerName: parsedJson["employee_name"], - hospitalId: parsedJson["client"], - reportID: parsedJson["service_report_nid"] is String - ? parsedJson["service_report_nid"] - : null , - viewReport: parsedJson["service_report_nid"] is bool ? false : true, - deviceModel: parsedJson["device_model"], - engineerMobile: parsedJson["engineer_mobile"], - faultDescription: parsedJson["fault_desc"], - jobSheetNumber: parsedJson["job_sheet_number"], - visitDate: parsedJson["visit_date"], - nextVisitDate:parsedJson["next_visit_date"] == null - ? null : DateTime.fromMillisecondsSinceEpoch(int.tryParse(parsedJson["next_visit_date"]) * 1000), - workPerformed: parsedJson["work_performed"], + id: parsedJson["id"].toString(), + requestCode: parsedJson["callNo"].toString(), + hospitalName: parsedJson["asset"]["site"]["custName"], + deviceNumber: parsedJson["asset"]["assetNumber"].toString(), + deviceId: parsedJson["asset"]["id"], + audio: URLs.getFileUrl(parsedJson["voiceNote"] ?? ""), + deviceArName: parsedJson["asset"]["modelDefinition"]["assetName"] ?? "", + deviceEnName: parsedJson["asset"]["modelDefinition"]["assetName"] ?? "", + devicePhotos: images, + deviceSerialNumber: parsedJson["asset"]["assetSerialNo"], + date: DateTime.tryParse(parsedJson["requestedDate"] ?? "").toString().split(" ").first, + // todo. add requeste time param for time + callComments: parsedJson["callComments"], + comments: parsedJson["comments"], + statusLabel: parsedJson["status"] == null ? null : parsedJson["status"]["name"], + statusValue: parsedJson["status"] == null ? null : parsedJson["status"]["value"], + statusId: parsedJson["status"] == null ? null : parsedJson["status"]["id"], + departmentName: parsedJson["asset"]["department"] != null ? parsedJson["asset"]["department"]["name"] : "", + engineerName: parsedJson["assignedEmployee"] == null ? null : parsedJson["assignedEmployee"]["name"], + engineerId: parsedJson["assignedEmployee"] == null ? null : parsedJson["assignedEmployee"]["id"], + hospitalId: parsedJson["asset"]["site"]["id"], + reportID: parsedJson["workOrder"] != null ? parsedJson["workOrder"]["workOrderId"] : null, + viewReport: parsedJson["workOrder"] != null, + deviceModel: parsedJson["asset"]["modelDefinition"]["modelName"], + engineerMobile: parsedJson["assignedEmployee"] == null ? null : parsedJson["assignedEmployee"]["phone"], + faultDescription: parsedJson["workOrder"] != null ? parsedJson["workOrder"]["faultDescription"] : null, + jobSheetNumber: parsedJson["workOrder"] != null ? parsedJson["workOrder"]["jobSheetNumber"] : null, + visitDate: DateTime.tryParse(parsedJson["visitDate"] ?? "").toString().split(" ").first, + nextVisitDate: DateTime.tryParse(parsedJson["nextVisitDate"] ?? ""), + workPerformed: parsedJson["workOrder"] != null ? parsedJson["workOrder"]["workPerformed"] : null, + device: Device.fromJson(parsedJson["asset"]), + reviewComment: parsedJson["reviewComment"], + type: Lookup.fromJson(parsedJson['typeofRequest']), + defectType: Lookup.fromJson(parsedJson['defectType']), + loanAvailability: Lookup.fromJson(parsedJson['loanAvailability']), + firstAction: Lookup.fromJson(parsedJson['firstAction']), + requestedThrough: Lookup.fromJson(parsedJson['requestedThrough']), + priority: Lookup.fromJson(parsedJson['priority']), ); } -} \ No newline at end of file +} diff --git a/lib/models/service_request/service_request_search.dart b/lib/models/service_request/service_request_search.dart index 257f25f5..6df51b1a 100644 --- a/lib/models/service_request/service_request_search.dart +++ b/lib/models/service_request/service_request_search.dart @@ -1,46 +1,90 @@ -class ServiceRequestSearch{ +import 'package:test_sa/models/hospital.dart'; +import 'package:test_sa/models/lookup.dart'; + +import '../call_request_for_work_order_model.dart'; + +class ServiceRequestSearch { + String callId; String deviceSerialNumber; + String deviceNumber; String deviceName; - String hospital; + Hospital hospital; String model; - int statusValue; - + Lookup statusValue; + bool mostRecent; + String from, to; + Lookup dateOperator; + AssignedEmployee assignedEmployee; ServiceRequestSearch({ this.deviceSerialNumber, + this.deviceNumber, this.statusValue, this.deviceName, this.model, this.hospital, + this.mostRecent, + this.callId, + this.from, + this.to, + this.assignedEmployee, + this.dateOperator, }); - fromSearch(ServiceRequestSearch newSearch){ + fromSearch(ServiceRequestSearch newSearch) { deviceSerialNumber = newSearch.deviceSerialNumber; + deviceNumber = newSearch.deviceNumber; statusValue = newSearch.statusValue; hospital = newSearch.hospital; model = newSearch.model; + mostRecent = newSearch.mostRecent; + callId = newSearch.callId; + from = newSearch.from; + to = newSearch.to; + assignedEmployee = newSearch.assignedEmployee; + dateOperator = newSearch.dateOperator; } - String toSearchString(){ - String _search = ""; - if(deviceSerialNumber != null && deviceSerialNumber.isNotEmpty){ - _search += "&sn_id=$deviceSerialNumber"; + Map toMap() { + Map search = {}; + if (deviceSerialNumber != null && deviceSerialNumber.isNotEmpty) { + search["assetSerialNumber"] = deviceSerialNumber; + } + + if (deviceNumber != null && deviceNumber.isNotEmpty) { + search["assetNo"] = deviceNumber; + } + + if (statusValue != null) { + search["status"] = statusValue.toMap(); + } + + if (deviceName != null && deviceName.isNotEmpty) { + search["assetName"] = deviceName; } - if(statusValue != null){ - _search += "&status=$statusValue"; + if (hospital != null) { + search["site"] = hospital.name; } - if(deviceName != null && deviceName.isNotEmpty){ - _search += "&equipment_en_name=$deviceName"; + if (model != null && model.isNotEmpty) { + search["modelDefinition"] = model; } - if(hospital != null && hospital.isNotEmpty){ - _search += "&client=$hospital"; + if (callId != null && callId.isNotEmpty) { + search["callId"] = callId; + } + + if (dateOperator != null && from != null) { + search["requestedDateSymbol"] = dateOperator.toMap(); + search["requestedDateFrom"] = from; + } + if (dateOperator != null && to != null) { + search["requestedDateTo"] = to; } - if(model != null && model.isNotEmpty){ - _search += "&model=$model"; + if (assignedEmployee != null) { + search["assignedEmployee"] = assignedEmployee.toJson(); } - return _search; + return search; } -} \ No newline at end of file +} diff --git a/lib/models/subtitle.dart b/lib/models/subtitle.dart index a2f212c2..fe71b3c3 100644 --- a/lib/models/subtitle.dart +++ b/lib/models/subtitle.dart @@ -1,6 +1,6 @@ import 'package:meta/meta.dart'; -class Subtitle{ +class Subtitle { // http requests status messages String currentlyServiceNotAvailable; String waitUntilYourRequestComplete; @@ -84,6 +84,7 @@ class Subtitle{ String hospital; String device; String deviceImages; + String deviceFiles; String pickDevice; String maintenanceIssue; String create; @@ -112,7 +113,6 @@ class Subtitle{ String unite; String unitRequired; String deviceArName; - String deviceEnName; String details; String general; String serviceRequestInformation; @@ -197,7 +197,7 @@ class Subtitle{ String customer; String reportType; String requiredWord; - String serviceType; + String assetType; String reportStatus; String callLastSituation; String invoiceNumber; @@ -206,17 +206,39 @@ class Subtitle{ String reasons; String attachImage; String operatingHours; - String partNumber; + String partNumberName; String number; String quantity; + String orderWorkNumber; + String assignedEmployee; + String assetSN; + String assetName; + String assetNumber; + String site; + String maintenanceSituation; + String currentSituation; // all String duplicateRequest; String duplicateAlert; String duplicateAlertMessage; String alert; + String comment; + String updateServiceRequest; + String repairLocation; + String travelingExpense; + String startDate; + String endDate; + String requestedQuantity; + String deliveredQuantity; + String destinationSite; + String building; + String floor; + String department; + String room; + String actions; - void setIssues(List issues){ + void setIssues(List issues) { issues.clear(); issues.add(reason1); issues.add(reason2); @@ -226,6 +248,8 @@ class Subtitle{ } Subtitle({ + @required this.updateServiceRequest, + @required this.comment, @required this.currentlyServiceNotAvailable, @required this.waitUntilYourRequestComplete, @required this.requestCompleteSuccessfully, @@ -278,7 +302,6 @@ class Subtitle{ @required this.titleValidateMessage, @required this.to, @required this.urlNotFound, - @required this.nameExist, @required this.unitRequired, @required this.unite, @@ -328,7 +351,6 @@ class Subtitle{ @required this.twitter, @required this.add, @required this.code, - @required this.deviceEnName, @required this.deviceName, @required this.serialNumber, @required this.policy, @@ -338,6 +360,7 @@ class Subtitle{ @required this.createServiceRequest, @required this.delete, @required this.deviceImages, + @required this.deviceFiles, @required this.deviceRequired, @required this.general, @required this.maintenanceIssueRequired, @@ -384,7 +407,6 @@ class Subtitle{ @required this.pickImage, @required this.requiredImage, @required this.activationAlert, - @required this.callId, @required this.requiredWord, @required this.quantity, @@ -397,20 +419,42 @@ class Subtitle{ @required this.newServiceReport, @required this.number, @required this.operatingHours, - @required this.partNumber, + @required this.partNumberName, @required this.reasons, @required this.reportStatus, @required this.reportType, - @required this.serviceType, + @required this.assetType, @required this.workPreformed, @required this.alert, @required this.duplicateAlert, @required this.duplicateAlertMessage, @required this.duplicateRequest, + @required this.orderWorkNumber, + @required this.assignedEmployee, + @required this.assetSN, + @required this.assetName, + @required this.site, + @required this.maintenanceSituation, + @required this.currentSituation, + @required this.repairLocation, + @required this.travelingExpense, + @required this.startDate, + @required this.endDate, + @required this.requestedQuantity, + @required this.deliveredQuantity, + @required this.assetNumber, + @required this.destinationSite, + @required this.building, + @required this.floor, + @required this.department, + @required this.room, + @required this.actions, }); - factory Subtitle.fromJson(Map parsedJson){ + factory Subtitle.fromJson(Map parsedJson) { return Subtitle( + updateServiceRequest: parsedJson["updateServiceRequest"], + comment: parsedJson["comment"], currentlyServiceNotAvailable: parsedJson["server_error_message"], failedToCompleteRequest: parsedJson["failed_request_message"], requestCompleteSuccessfully: parsedJson["successful_request_message"], @@ -423,7 +467,6 @@ class Subtitle{ signOut: parsedJson["sign_out"], signOutAlert: parsedJson["logout_alert"], language: parsedJson["language"], - name: parsedJson["name"], email: parsedJson["email"], phoneNumber: parsedJson["phone_number"], @@ -437,7 +480,6 @@ class Subtitle{ passwordValidateMessage: parsedJson["password_validate_message"], confirmPasswordValidateMessage: parsedJson["confirm_password_validate_message"], phoneNumberValidateMessage: parsedJson["phone_number_validate_message"], - forgetPasswordWithMark: parsedJson["forget_password_with_mark"], showPassword: parsedJson["show_password"], wrongEmailOrPassword: parsedJson["wrong_email_or_password"], @@ -447,7 +489,6 @@ class Subtitle{ back: parsedJson["back"], search: parsedJson["search"], searchByName: parsedJson["search_by_name"], - address: parsedJson["address"], addressNotFound: parsedJson["address_not_found"], addressValidateMessage: parsedJson["address_validate_message"], @@ -466,7 +507,6 @@ class Subtitle{ titleNotFound: parsedJson["title_not_found"], titleValidateMessage: parsedJson["title_validate_message"], urlNotFound: parsedJson["url_not_found"], - date: parsedJson["date"], status: parsedJson["status"], code: parsedJson["code"], @@ -481,8 +521,8 @@ class Subtitle{ details: parsedJson["details"], device: parsedJson["device"], deviceArName: parsedJson["deviceArName"], - deviceEnName: parsedJson["deviceEnName"], deviceImages: parsedJson["deviceImages"], + deviceFiles: parsedJson["deviceFiles"], deviceModel: parsedJson["deviceModel"], deviceName: parsedJson["deviceName"], deviceRequired: parsedJson["deviceRequired"], @@ -542,7 +582,6 @@ class Subtitle{ visitDate: parsedJson["visitDate"], whatsApp: parsedJson["whatsApp"], workPerformed: parsedJson["workPerformed"], - actualDate: parsedJson["actualDate"], done: parsedJson["done"], expectDate: parsedJson["expectDate"], @@ -573,7 +612,6 @@ class Subtitle{ requiredImage: parsedJson["requiredImage"], taskStatus: parsedJson["taskStatus"], activationAlert: parsedJson["activationAlert"], - attachImage: parsedJson["attachImage"], callLastSituation: parsedJson["callLastSituation"], customer: parsedJson["customer"], @@ -583,21 +621,39 @@ class Subtitle{ newServiceReport: parsedJson["newServiceReport"], number: parsedJson["number"], operatingHours: parsedJson["operatingHours"], - partNumber: parsedJson["partNumber"], + partNumberName: parsedJson["partNumberName"], quantity: parsedJson["quantity"], reasons: parsedJson["reasons"], reportStatus: parsedJson["reportStatus"], reportType: parsedJson["reportType"], callId: parsedJson["callId"], requiredWord: parsedJson["requiredWord"], - serviceType: parsedJson["serviceType"], + assetType: parsedJson["AssetType"], workPreformed: parsedJson["workPreformed"], - alert: parsedJson["alert"], duplicateAlert: parsedJson["duplicateAlert"], duplicateAlertMessage: parsedJson["duplicateAlertMessage"], duplicateRequest: parsedJson["duplicateRequest"], + orderWorkNumber: parsedJson["orderWorkNumber"], + assignedEmployee: parsedJson["assignedEmployee"], + assetSN: parsedJson["assetSN"], + assetName: parsedJson["assetName"], + assetNumber: parsedJson["assetNumber"], + site: parsedJson["site"], + maintenanceSituation: parsedJson["maintenanceSituation"], + currentSituation: parsedJson["currentSituation"], + repairLocation: parsedJson["repairLocation"], + travelingExpense: parsedJson["travelingExpense"], + startDate: parsedJson["startDate"], + endDate: parsedJson["endDate"], + requestedQuantity: parsedJson["requestedQuantity"], + deliveredQuantity: parsedJson["deliveredQuantity"], + destinationSite: parsedJson["destinationSite"], + building: parsedJson["building"], + floor: parsedJson["floor"], + department: parsedJson["department"], + room: parsedJson["room"], + actions: parsedJson["actions"], ); } - -} \ No newline at end of file +} diff --git a/lib/models/timer_model.dart b/lib/models/timer_model.dart index 191128fd..a0854b47 100644 --- a/lib/models/timer_model.dart +++ b/lib/models/timer_model.dart @@ -3,5 +3,7 @@ class TimerModel { DateTime endAt; int durationInSecond; - TimerModel({this.startAt,this.endAt,this.durationInSecond}); -} \ No newline at end of file + // bool stopped; + + TimerModel({this.startAt, this.endAt, this.durationInSecond}); +} diff --git a/lib/models/user.dart b/lib/models/user.dart index caa9e7fb..ee567784 100644 --- a/lib/models/user.dart +++ b/lib/models/user.dart @@ -1,111 +1,229 @@ import 'package:test_sa/controllers/notification/firebase_notification_manger.dart'; -import 'package:test_sa/models/department.dart'; import 'package:test_sa/models/enums/user_types.dart'; -import 'package:test_sa/models/hospital.dart'; class User { + int clientId; + String clientName; + List departmentId; + List departmentName; + String message; + String username; + String userID; + String email; + String password; + String token; + dynamic roles; + List userRoles; + String tokenlife; + bool isAuthenticated; + bool hasError; + String profilePhotoName; String id; String userName; - String password; - String email; - String image; - Hospital hospital; - Department department; - UsersTypes type; + String normalizedUserName; + String normalizedEmail; + bool emailConfirmed; + dynamic passwordHash; + String securityStamp; + String concurrencyStamp; String phoneNumber; - String whatsApp; - String token; - bool isActive; + bool phoneNumberConfirmed; + bool twoFactorEnabled; + dynamic lockoutEnd; + bool lockoutEnabled; + int accessFailedCount; - User( - {this.id, - this.userName = "", - this.email = "", - this.password = "", - this.phoneNumber = "", - this.hospital, - this.image, - this.department, - this.type, - this.whatsApp, - this.token, - this.isActive = false}); + User({ + this.clientId, + this.clientName, + this.departmentId, + this.departmentName, + this.message, + this.username, + this.userID, + this.email, + this.password, + this.token, + this.roles, + this.userRoles, + this.tokenlife, + this.isAuthenticated, + this.hasError, + this.profilePhotoName, + this.id, + this.userName, + this.normalizedUserName, + this.normalizedEmail, + this.emailConfirmed, + this.passwordHash, + this.securityStamp, + this.concurrencyStamp, + this.phoneNumber, + this.phoneNumberConfirmed, + this.twoFactorEnabled, + this.lockoutEnd, + this.lockoutEnabled, + this.accessFailedCount, + }); Future> toLoginJson() async { if (FirebaseNotificationManger.token == null) await FirebaseNotificationManger.getToken(); return { "username": userName, - "pass": password, - "firebase_token": FirebaseNotificationManger?.token ?? "", + "password": password, + "fireBaseToken": FirebaseNotificationManger?.token ?? "", }; } + UsersTypes get type { + switch (userRoles?.first?.name) { + case "Engineer": + return UsersTypes.engineer; + case "Hospital": + return UsersTypes.normal_user; + default: + return null; + } + } + Map toUpdateProfileJson() { Map jsonObject = {}; - if (department?.id != null && department.id.isNotEmpty) jsonObject["department"] = department.id; - if (whatsApp != null && whatsApp.isNotEmpty) jsonObject["whatsapp"] = whatsApp; - if (phoneNumber != null && phoneNumber.isNotEmpty) jsonObject["phone"] = phoneNumber; + // if (departmentId != null) jsonObject["department"] = departmentId; + // if (whatsApp != null && whatsApp.isNotEmpty) jsonObject["whatsapp"] = whatsApp; + // if (phoneNumber != null && phoneNumber.isNotEmpty) jsonObject["phone"] = phoneNumber; return jsonObject; } Future> toRegisterJson() async { - if (FirebaseNotificationManger.token == null) await FirebaseNotificationManger.getToken(); + // if (FirebaseNotificationManger.token == null) await FirebaseNotificationManger.getToken(); return { - "username": userName, - "email": email, - "whatsapp": whatsApp, - "client": hospital.id, - "department": department?.id, - "phone": phoneNumber, - "pass": password, - "firebase_token": FirebaseNotificationManger?.token ?? "", + // "username": userName, + // "email": email, + // "whatsapp": whatsApp, + // "client": hospital.id, + // "department": department?.id, + // "phone": phoneNumber, + // "pass": password, + // "firebase_token": FirebaseNotificationManger?.token ?? "", }; } Map toJson() { - return { - "uid": id, - "name": userName, - "email": email, - "token": token, - "phone": phoneNumber, - "whatsapp": whatsApp, - "client": hospital?.id, - "client_name": hospital?.name, - "department": department?.id, - "department_name": department?.name, - "password": password, - "picture": image, - "active": isActive ? 1 : 0, - "role": type == UsersTypes.engineer ? "field_engineer" : "normal_user", - // "token":token, pass is token - }; + final map = {}; + map['client_id'] = clientId; + map['client_name'] = clientName; + map['department_id'] = departmentId; + map['department_name'] = departmentName; + map['message'] = message; + map['username'] = username; + map['userID'] = userID; + map['email'] = email; + map['password'] = password; + map['token'] = token; + map['roles'] = roles; + if (userRoles != null) { + map['userRoles'] = userRoles.map((v) => v.toJson()).toList(); + } + map['tokenlife'] = tokenlife; + map['isAuthenticated'] = isAuthenticated; + map['hasError'] = hasError; + map['profilePhotoName'] = profilePhotoName; + map['id'] = id; + map['userName'] = userName; + map['normalizedUserName'] = normalizedUserName; + map['normalizedEmail'] = normalizedEmail; + map['emailConfirmed'] = emailConfirmed; + map['passwordHash'] = passwordHash; + map['securityStamp'] = securityStamp; + map['concurrencyStamp'] = concurrencyStamp; + map['phoneNumber'] = phoneNumber; + map['phoneNumberConfirmed'] = phoneNumberConfirmed; + map['twoFactorEnabled'] = twoFactorEnabled; + map['lockoutEnd'] = lockoutEnd; + map['lockoutEnabled'] = lockoutEnabled; + map['accessFailedCount'] = accessFailedCount; + return map; } - factory User.fromJson(Map parsedJson) { - UsersTypes type; - switch (parsedJson["role"]) { - case "field_engineer": - type = UsersTypes.engineer; - break; - default: - type = UsersTypes.normal_user; - break; + User.fromJson(dynamic json) { + clientId = json['client_id']; + clientName = json['client_name']; + if (json['department_id'] != null) { + departmentId = []; + json['department_id'].forEach((v) { + departmentId.add(v); + }); } - return User( - id: parsedJson["uid"], - userName: parsedJson["name"] ?? parsedJson["title"], - email: parsedJson["mail"] ?? parsedJson["email"], - hospital: Hospital(id: parsedJson["client"], name: parsedJson["client_name"]), - department: Department( - id: parsedJson["department"], - name: parsedJson["department_name"], - ), - image: parsedJson["picture"], - phoneNumber: parsedJson["phone"], - whatsApp: parsedJson["whatsapp"], - token: parsedJson["token"], - isActive: parsedJson["active"] == "1", - type: type); + if (json['department_name'] != null) { + departmentId = []; + json['department_name'].forEach((v) { + departmentId.add(v); + }); + } + message = json['message']; + username = json['username']; + userID = json['userID']; + email = json['email']; + password = json['password']; + token = json['token']; + roles = json['roles']; + if (json['userRoles'] != null) { + userRoles = []; + json['userRoles'].forEach((v) { + userRoles.add(UserRoles.fromJson(v)); + }); + } + tokenlife = json['tokenlife']; + isAuthenticated = json['isAuthenticated']; + hasError = json['hasError']; + profilePhotoName = json['profilePhotoName']; + id = json['id']; + userName = json['userName']; + normalizedUserName = json['normalizedUserName']; + normalizedEmail = json['normalizedEmail']; + emailConfirmed = json['emailConfirmed']; + passwordHash = json['passwordHash']; + securityStamp = json['securityStamp']; + concurrencyStamp = json['concurrencyStamp']; + phoneNumber = json['phoneNumber']; + phoneNumberConfirmed = json['phoneNumberConfirmed']; + twoFactorEnabled = json['twoFactorEnabled']; + lockoutEnd = json['lockoutEnd']; + lockoutEnabled = json['lockoutEnabled']; + accessFailedCount = json['accessFailedCount']; + } +} + +class UserRoles { + UserRoles({ + this.id, + this.name, + this.value, + }); + + UserRoles.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + } + String id; + String name; + String value; + UserRoles copyWith({ + String id, + String name, + String value, + }) => + UserRoles( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + ); + Map toJson() { + final map = {}; + map['id'] = id; + map['name'] = name; + map['value'] = value; + return map; } } diff --git a/lib/models/visits/visit.dart b/lib/models/visits/visit.dart index b6562e4c..9d8ad663 100644 --- a/lib/models/visits/visit.dart +++ b/lib/models/visits/visit.dart @@ -1,20 +1,23 @@ import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/pantry/pentry.dart'; -class Visit{ - String id; +class Visit { + int id; String serialNumber; String expectDate; String actualDate; - String hospitalId; + String createdOn; + int hospitalId; String hospitalName; - String deviceId; + int deviceId; + int ppmScheduleId; String deviceSerialNumber; String deviceArabicName; String deviceEnglishName; String employId; String employName; String modelAndBrand; - String contactStatus; + Pentry pentry; Lookup status; String assignTo; String deviceNumber; @@ -22,6 +25,7 @@ class Visit{ Visit({ this.id, + this.ppmScheduleId, this.serialNumber, this.hospitalId, this.hospitalName, @@ -35,35 +39,44 @@ class Visit{ this.actualDate, this.status, this.modelAndBrand, - this.contactStatus, + this.pentry, this.images, this.assignTo, this.deviceNumber, + this.createdOn, }); - factory Visit.fromJson(Map parsedJson){ + factory Visit.fromJson(Map parsedJson) { + List images = []; + if (parsedJson["vAttachments"] is List) { + List list = parsedJson["vAttachments"]; + images = list.map((e) => e["attachmentURL"].toString()).toList(); + } return Visit( - id: parsedJson["nid"], - serialNumber: parsedJson["title"], - hospitalId: parsedJson["client"], - deviceNumber: parsedJson["device_no"], - hospitalName: parsedJson["client_name"], - deviceId: parsedJson["medical_equipment_nid"], - deviceSerialNumber: parsedJson["medical_equipment"], - deviceEnglishName: parsedJson["equipment_english_name"], - deviceArabicName: parsedJson["equipment_arabic_name"], - employId: parsedJson["assigned_employee"], - employName: parsedJson["assigned_employee_name"], - expectDate: parsedJson["expected_date"], - actualDate: parsedJson["actual_date"], - modelAndBrand: parsedJson["mode_brand"], - contactStatus: parsedJson["contactStatus"], - images: List.from(parsedJson["images"] ?? []), + id: parsedJson["id"], + serialNumber: parsedJson["visitCode"], + ppmScheduleId: parsedJson["ppmScheduleId"], + hospitalId: parsedJson["siteId"], + deviceNumber: parsedJson["assetNumber"], + hospitalName: parsedJson["siteName"], + deviceId: parsedJson["assetId"], + deviceSerialNumber: parsedJson["assetSerialNo"], + deviceEnglishName: parsedJson["assetName"], + deviceArabicName: parsedJson["assetName"], + employId: parsedJson["assignedEmployeeId"].toString(), + employName: parsedJson["assignedEmployeeName"], + expectDate: parsedJson["expectedDate"].toString().split("T").first, + actualDate: parsedJson["actualDate"].toString().split("T").first, + modelAndBrand: "${parsedJson["modelName"]} / ${parsedJson["manufacturerName"]}", + // contactStatus: parsedJson["contactStatus"], + images: images, status: Lookup( - id: int.tryParse(parsedJson["status"] ?? "-1"), // actual value (0,1,2) - label: parsedJson["status_value"] // text value - ), - assignTo: parsedJson["assigned_to"], + id: parsedJson["visitStatusId"], // actual value (0,1,2) + name: parsedJson["visitStatusName"] // text value + ), + assignTo: parsedJson["assignedToName"], + pentry: Pentry.fromMap(parsedJson), + createdOn: parsedJson['createdOn'], ); } -} \ No newline at end of file +} diff --git a/lib/models/visits/visits_group.dart b/lib/models/visits/visits_group.dart index abe6dfc0..7ced9b3b 100644 --- a/lib/models/visits/visits_group.dart +++ b/lib/models/visits/visits_group.dart @@ -1,45 +1,45 @@ - -import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/engineer.dart'; import 'package:test_sa/models/visits/visit.dart'; -class VisitsGroup{ - String userId; - String workingHours; - String travelingHours; - String jobSheetNumber; - String image; - Lookup status; - Lookup taskStatus; - DateTime date; +class VisitsGroup { + // String userId; + // String workingHours; + // String travelingHours; + // String jobSheetNumber; + // String image; + // Lookup status; + // Lookup taskStatus; + // DateTime date; + Engineer engineer; List visits; VisitsGroup({ - this.userId, - this.status, - this.date, - this.jobSheetNumber, - this.travelingHours, - this.workingHours, + // this.userId, + // this.status, + // this.date, + // this.jobSheetNumber, + // this.travelingHours, + // this.workingHours, this.visits, - this.image, - this.taskStatus, + this.engineer, + // this.image, + // this.taskStatus, }); - Map toJson(){ - Map jsonObject = {}; - jsonObject["nids"] = visits.map((e) => e.id).toList().join(','); - if(status != null) jsonObject["status"] = status.id.toString(); - if(date != null) jsonObject["date"] = date.toString().split(" ").first; - if(jobSheetNumber != null && jobSheetNumber.isNotEmpty) - jsonObject["job_sheet_no"] = jobSheetNumber; - if(travelingHours != null && travelingHours.isNotEmpty) - jsonObject["traveling_hours"] = travelingHours; - if(workingHours != null && workingHours.isNotEmpty) - jsonObject["working_hours"] = workingHours; - if(image != null) jsonObject["image"] = image; - if(taskStatus != null) jsonObject["task_status"] = taskStatus.id.toString(); + Map toJson() { + Map jsonObject = {}; + jsonObject["ids"] = visits.map((e) => e.id).toList(); + jsonObject["assignedEmployeeId"] = engineer?.id; + // if(status != null) jsonObject["taskStatusId"] = status.id.toString(); + // if(date != null) jsonObject["actualDate"] = date.toIso8601String(); + // if(jobSheetNumber != null && jobSheetNumber.isNotEmpty) + // jsonObject["jobSheetNo"] = jobSheetNumber; + // if(travelingHours != null && travelingHours.isNotEmpty) + // jsonObject["travelingHours"] = travelingHours; + // if(workingHours != null && workingHours.isNotEmpty) + // jsonObject["workingHours"] = workingHours; + // if(image != null) jsonObject["image"] = image; + // if(taskStatus != null) jsonObject["task_status"] = taskStatus.id.toString(); return jsonObject; } - - -} \ No newline at end of file +} diff --git a/lib/models/visits/visits_search.dart b/lib/models/visits/visits_search.dart index 7cfd4ceb..4e6159f2 100644 --- a/lib/models/visits/visits_search.dart +++ b/lib/models/visits/visits_search.dart @@ -1,32 +1,41 @@ -class VisitsSearch{ +import 'package:test_sa/models/hospital.dart'; +import 'package:test_sa/models/lookup.dart'; + +class VisitsSearch { String deviceSerialNumber; - String hospitalName; + String deviceName; + String deviceNumber; + Hospital hospital; String brand; - String model; - String contactStatus; + Lookup model; + Lookup contactStatus; DateTime expectedDateFrom; DateTime expectedDateTo; DateTime actualDateFrom; DateTime actualDateTo; - int statusValue; + Lookup statusValue; + bool mostRecent; VisitsSearch({ this.deviceSerialNumber, this.statusValue, this.brand, - this.hospitalName, + this.hospital, this.actualDateTo, this.actualDateFrom, this.model, this.contactStatus, this.expectedDateFrom, this.expectedDateTo, + this.deviceNumber, + this.deviceName, + this.mostRecent, }); - fromSearch(VisitsSearch newSearch){ + fromSearch(VisitsSearch newSearch) { deviceSerialNumber = newSearch.deviceSerialNumber; brand = newSearch.brand; - hospitalName = newSearch.hospitalName; + hospital = newSearch.hospital; actualDateTo = newSearch.actualDateTo; actualDateFrom = newSearch.actualDateFrom; model = newSearch.model; @@ -34,50 +43,53 @@ class VisitsSearch{ expectedDateFrom = newSearch.expectedDateFrom; expectedDateTo = newSearch.expectedDateTo; statusValue = newSearch.statusValue; + mostRecent = newSearch.mostRecent; + deviceNumber = newSearch.deviceNumber; + deviceName = newSearch.deviceName; } - String toSearchString(){ - String _search = ""; - if(deviceSerialNumber != null && deviceSerialNumber.isNotEmpty){ - _search += "&sn_id=$deviceSerialNumber"; + Map toMap() { + Map _search = {}; + if (deviceSerialNumber != null && deviceSerialNumber.isNotEmpty) { + _search["assetId"] = deviceSerialNumber; } - if(hospitalName != null && hospitalName.isNotEmpty){ - _search += "&client=$hospitalName"; + if (hospital != null) { + _search["siteId"] = hospital.id; } - if(brand != null && brand.isNotEmpty){ - _search += "&brand=$brand"; + if (brand != null && brand.isNotEmpty) { + // todo get new key + _search[""] = brand; } - if(model != null && model.isNotEmpty){ - _search += "&model=$model"; + if (model != null) { + _search["modelId"] = model.id; } - if(expectedDateFrom != null){ - _search += "&expected_date_from=${expectedDateFrom.millisecondsSinceEpoch ~/ 1000}"; + if (expectedDateFrom != null) { + _search["expectedDateFrom"] = expectedDateFrom.toIso8601String(); } - if(expectedDateTo != null){ - _search += "&expected_date_to=${expectedDateTo.millisecondsSinceEpoch~/1000}"; + if (expectedDateTo != null) { + _search["expectedDateTo"] = expectedDateTo.toIso8601String(); } - if(actualDateFrom != null){ - _search += "&actual_date_from=${actualDateFrom.millisecondsSinceEpoch ~/ 1000}"; + if (actualDateFrom != null) { + _search["actualDateFrom"] = actualDateFrom.toIso8601String(); } - if(actualDateTo != null){ - _search += "&actual_date_to=${actualDateTo.millisecondsSinceEpoch~/1000}"; + if (actualDateTo != null) { + _search["actualDateTo"] = actualDateTo.toIso8601String(); } - if(statusValue != null){ - _search += "&status=$statusValue"; + if (statusValue != null) { + _search["visitStatusId"] = statusValue.id; } - if(contactStatus != null){ - _search += "&assigned_to=$contactStatus"; + if (contactStatus != null) { + _search["assignedToId"] = contactStatus.id; } return _search; } } - diff --git a/lib/views/app_style/colors.dart b/lib/views/app_style/colors.dart index b6200b0e..fb1aa4b2 100644 --- a/lib/views/app_style/colors.dart +++ b/lib/views/app_style/colors.dart @@ -1,41 +1,50 @@ import 'package:flutter/material.dart'; -import 'package:test_sa/models/lookup.dart'; + class AColors { AColors._(); - static const Color white = Color(0xffffffff); - static const Color black = Color(0xff000000); - static const Color grey3A = Color(0xff2e303a); - static const Color grey = Color(0xffe1e7e7); - static const green = Colors.green; - static const Color orange = Colors.orange; - static const Color deepOrange = Colors.deepOrangeAccent; - static const Color red = Colors.red; - static const Color deepRed = Color(0xFFD32F2F); + + static const Color white = Color(0xffffffff); + static const Color black = Color(0xff000000); + static const Color grey3A = Color(0xff2e303a); + static const Color grey = Color(0xffe1e7e7); + static const green = Colors.green; + static const Color orange = Colors.orange; + static const Color deepOrange = Colors.deepOrangeAccent; + static const Color red = Colors.red; + static const Color deepRed = Color(0xFFD32F2F); static const Color scaffoldBackgroundColor = Color(0xffffffff); - static const Color secondaryColor = Color(0xff111427); - static const Color primaryColor = Color(0xff5bb0da); - static const Color cyan = Color(0xff4A8DB7); - static const Color onPrimaryColor = Color(0xffffffff); + static const Color secondaryColor = Color(0xff111427); + static const Color primaryColor = Color(0xff5bb0da); + static const Color cyan = Color(0xff4A8DB7); + static const Color onPrimaryColor = Color(0xffffffff); static Color inputFieldBackgroundColor = Color(0xfff5f5f5); static Color greyEF = Color(0xffEFEFEF); - static Color getRequestStatusColor(int id){ - switch(id){ - case 4: return AColors.deepRed; - case 6: return AColors.green; - case 5: return AColors.orange; - case 8: return AColors.green; - case 9: return AColors.orange; - default : return AColors.grey; + static Color getRequestStatusColor(int id) { + switch (id) { + case 4: + return AColors.deepRed; + case 6: + return AColors.green; + case 5: + return AColors.orange; + case 8: + return AColors.green; + case 9: + return AColors.orange; + default: + return AColors.grey; } } - static Color getGasStatusColor(int id){ - switch(id){ - case 0: return AColors.orange; - case 1: return AColors.green; - default : return AColors.grey; + static Color getGasStatusColor(int id) { + switch (id) { + case 0: + return AColors.orange; + case 1: + return AColors.green; + default: + return AColors.grey; } } } - diff --git a/lib/views/app_style/sizing.dart b/lib/views/app_style/sizing.dart index bb66b317..e14f3bce 100644 --- a/lib/views/app_style/sizing.dart +++ b/lib/views/app_style/sizing.dart @@ -1,39 +1,31 @@ import 'package:flutter/material.dart'; + class AppStyle { AppStyle._(); static const double borderRadius = 10; - static const BoxShadow boxShadow = BoxShadow( - color: Colors.black26, - blurRadius: 3, - offset: Offset(0,2) - ); + static const BoxShadow boxShadow = BoxShadow(color: Colors.black26, blurRadius: 3, offset: Offset(0, 2)); - static double getBorderRadius(BuildContext context){ + static double getBorderRadius(BuildContext context) { return borderRadius * getScaleFactor(context); } - static double getScaleFactor(BuildContext context){ + static double getScaleFactor(BuildContext context) { return MediaQuery.of(context).orientation == Orientation.portrait - ? MediaQuery.of(context).size.width/(360) > 1.5 - ? 1.5 : MediaQuery.of(context).size.width/(360) - : MediaQuery.of(context).size.height/(360) > 1.5 - ? 1.5 : MediaQuery.of(context).size.height/(360); + ? MediaQuery.of(context).size.width / (360) > 1.5 + ? 1.5 + : MediaQuery.of(context).size.width / (360) + : MediaQuery.of(context).size.height / (360) > 1.5 + ? 1.5 + : MediaQuery.of(context).size.height / (360); } - static BorderRadius getCardBorder(BuildContext context){ + static BorderRadius getCardBorder(BuildContext context) { return BorderRadius.only( - topRight: Radius.circular( - AppStyle.borderRadius * AppStyle.getScaleFactor(context) - ), - topLeft: Radius.circular( - AppStyle.borderRadius * AppStyle.getScaleFactor(context) - ), - bottomRight: Radius.circular( - AppStyle.borderRadius * AppStyle.getScaleFactor(context) - ), + topRight: Radius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + topLeft: Radius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + bottomRight: Radius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), ); } - -} \ No newline at end of file +} diff --git a/lib/views/pages/device_transfer/device_transfer_details.dart b/lib/views/pages/device_transfer/device_transfer_details.dart index 7b36058c..2e807ec9 100644 --- a/lib/views/pages/device_transfer/device_transfer_details.dart +++ b/lib/views/pages/device_transfer/device_transfer_details.dart @@ -3,9 +3,7 @@ import 'package:provider/provider.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/device_transfer_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; -import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/device/device_transfer.dart'; -import 'package:test_sa/models/device/device_transfer_info.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; @@ -13,11 +11,15 @@ import 'package:test_sa/views/pages/device_transfer/update_device_transfer.dart' import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/buttons/app_small_button.dart'; import 'package:test_sa/views/widgets/device_trancfer/device_transfer_info_section.dart'; +import 'package:test_sa/views/widgets/loaders/app_loading.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/requests/info_row.dart'; +import '../../../models/enums/user_types.dart'; + class DeviceTransferDetails extends StatefulWidget { final DeviceTransfer model; + const DeviceTransferDetails({Key key, this.model}) : super(key: key); @override @@ -25,13 +27,10 @@ class DeviceTransferDetails extends StatefulWidget { } class _DeviceTransferDetailsState extends State { - - final DeviceTransferInfo _model = DeviceTransferInfo(); + DeviceTransfer _model; bool _isSender = false; bool _isReceiver = false; UserProvider _userProvider; - SettingProvider _settingProvider; - DeviceTransferProvider _deviceTransferProvider; bool _isLoading = false; Subtitle _subtitle; final GlobalKey _formKey = GlobalKey(); @@ -39,126 +38,164 @@ class _DeviceTransferDetailsState extends State { @override void initState() { - - + _model = widget.model; super.initState(); } + Future _getDeviceTransfer() async { + _model = await Provider.of(context).getRequestById(assetTransferId: widget.model.id); + } + @override Widget build(BuildContext context) { - _subtitle = AppLocalization.of(context).subtitle; - _userProvider = Provider.of(context); - _settingProvider = Provider.of(context); - _deviceTransferProvider = Provider.of(context); - _isSender = _userProvider.user.id == widget.model.sender?.userId; - _isReceiver = _userProvider.user.id == widget.model.receiver?.userId; return Scaffold( key: _scaffoldKey, body: SafeArea( - child: Form( - key: _formKey, - child: LoadingManager( - isLoading: _isLoading, - isFailedLoading: false, - stateCode: 200, - onRefresh: () async {}, - child: Column( - children: [ - Container( - color: Theme.of(context).colorScheme.primary, - padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), - child: Row( + child: FutureBuilder( + future: _getDeviceTransfer(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const ALoading(); + } else { + _subtitle = AppLocalization.of(context).subtitle; + _userProvider = Provider.of(context); + _isSender = _userProvider.user.userID == _model.sender?.userId; + _isReceiver = _userProvider.user.userID == _model.receiver?.userId; + return Form( + key: _formKey, + child: LoadingManager( + isLoading: _isLoading, + isFailedLoading: false, + stateCode: 200, + onRefresh: () async {}, + child: Column( children: [ - const ABackButton(), - Expanded( - child: Center( - child: Text( - _subtitle.details, - style: Theme.of(context).textTheme.headline6.copyWith( - color: AColors.white, - fontStyle: FontStyle.italic - ), - ), - ), - ), - const SizedBox(width: 58), - ], - ), - ), - Expanded( - child: SingleChildScrollView( - padding: EdgeInsets.all(16*AppStyle.getScaleFactor(context)), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - RequestInfoRow( - title: _subtitle.title, - info: widget.model.title, - ), - RequestInfoRow( - title: _subtitle.device, - info: widget.model.device.serialNumber, - ), - const SizedBox(height:8), - Row( + Container( + color: Theme.of(context).colorScheme.primary, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), + child: Row( children: [ + const ABackButton(), Expanded( - child: Text( - "Sender", - style: Theme.of(context).textTheme.headline6 + child: Center( + child: Text( + _subtitle.details, + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), + ), ), ), - if(_isSender) - ASmallButton( - text: _subtitle.edit, - onPressed: (){ - Navigator.of(context).push( - MaterialPageRoute( - builder: (_)=> UpdateDeviceTransfer(model: widget.model,isSender: _isSender,) - ) - ); - }, - ), + const SizedBox(width: 58), ], ), - const SizedBox(height:12), - DeviceTransferInfoSection( - info: widget.model.sender, - ), - const SizedBox(height:8), - Row( - children: [ - Expanded( - child: Text( - "Receiver", - style: Theme.of(context).textTheme.headline6 + ), + Expanded( + child: SingleChildScrollView( + padding: EdgeInsets.all(16 * AppStyle.getScaleFactor(context)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + RequestInfoRow( + title: "Transfer Id", + info: _model.title?.toString(), ), - ), - if(_isReceiver) - ASmallButton( - text: _subtitle.edit, - onPressed: (){ - Navigator.of(context).push( - MaterialPageRoute( - builder: (_)=> UpdateDeviceTransfer(model: widget.model,isSender: _isSender,) - ) - ); - }, - ), - ], - ), - const SizedBox(height:12), - DeviceTransferInfoSection( - info: widget.model.receiver, + RequestInfoRow( + title: _subtitle.assetName, + info: _model.device.assetName, + ), + RequestInfoRow( + title: _subtitle.assetSN, + info: _model.device.serialNumber, + ), + RequestInfoRow( + title: _subtitle.assetNumber, + info: _model.device.number, + ), + RequestInfoRow( + title: _subtitle.destinationSite, + info: _model.device.destSiteName, + ), + RequestInfoRow( + title: _subtitle.building, + info: _model.device.destBuildingName, + ), + RequestInfoRow( + title: _subtitle.floor, + info: _model.device.destFloor, + ), + RequestInfoRow( + title: _subtitle.department, + info: _model.device.destDepartmentName, + ), + RequestInfoRow( + title: _subtitle.room, + info: _model.device.destRoom, + ), + RequestInfoRow( + title: _subtitle.actions, + info: "", + ), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: Text("Sender", style: Theme.of(context).textTheme.headline6), + ), + if (_userProvider.user?.type == UsersTypes.engineer) + ASmallButton( + text: _subtitle.edit, + onPressed: (_isSender) + ? () { + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => UpdateDeviceTransfer( + model: _model, + isSender: true, + ))); + } + : null, + ), + ], + ), + const SizedBox(height: 12), + DeviceTransferInfoSection( + info: _model.sender, + isSender: true, + ), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: Text("Receiver", style: Theme.of(context).textTheme.headline6), + ), + if (_userProvider.user?.type == UsersTypes.engineer) + ASmallButton( + text: _subtitle.edit, + onPressed: (_isReceiver) + ? () { + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => UpdateDeviceTransfer( + model: _model, + isSender: false, + ))); + } + : null, + ), + ], + ), + const SizedBox(height: 12), + DeviceTransferInfoSection( + info: _model.receiver, + isSender: false, + ), + ], + ), ), - - ], - ), + ), + ], ), ), - ], - ), - ), + ); + } + }, ), ), ); diff --git a/lib/views/pages/device_transfer/request_device_transfer.dart b/lib/views/pages/device_transfer/request_device_transfer.dart index eaaed184..16eb104d 100644 --- a/lib/views/pages/device_transfer/request_device_transfer.dart +++ b/lib/views/pages/device_transfer/request_device_transfer.dart @@ -1,26 +1,31 @@ import 'package:flutter/material.dart'; -import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/http_status_manger/http_status_manger.dart'; import 'package:test_sa/controllers/providers/api/device_transfer_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/models/department.dart'; import 'package:test_sa/models/device/device_transfer.dart'; import 'package:test_sa/models/device/device_transfer_info.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; -import 'package:test_sa/views/widgets/departments/department_button.dart'; import 'package:test_sa/views/widgets/equipment/device_button.dart'; -import 'package:test_sa/views/widgets/hospitals/hospital_button.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; import '../../../../controllers/localization/localization.dart'; +import '../../../controllers/validator/validator.dart'; +import '../../app_style/colors.dart'; +import '../../widgets/app_text_form_field.dart'; +import '../../widgets/gas_refill/building_type_menu.dart'; +import '../../widgets/gas_refill/department_type_menu.dart'; +import '../../widgets/gas_refill/floor_type_menu.dart'; +import '../../widgets/hospitals/hospital_auto_complete_field_new.dart'; class RequestDeviceTransfer extends StatefulWidget { static const String id = "/request-device-transfer"; + const RequestDeviceTransfer({Key key}) : super(key: key); @override @@ -35,7 +40,7 @@ class _RequestDeviceTransferState extends State { SettingProvider _settingProvider; DeviceTransferProvider _deviceTransferProvider; final TextEditingController _requestedQuantityController = TextEditingController(); - final DeviceTransfer _formModel = DeviceTransfer(receiver: DeviceTransferInfo()); + final DeviceTransfer _formModel = DeviceTransfer(receiver: DeviceTransferInfo(), sender: DeviceTransferInfo()); final GlobalKey _formKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); @@ -59,7 +64,7 @@ class _RequestDeviceTransferState extends State { _isLoading = true; setState(() {}); - + // _formModel.sender?.client?.id = _userProvider.user?.clientId; int status = await _deviceTransferProvider.createRequest( user: _userProvider.user, host: _settingProvider.host, @@ -68,21 +73,23 @@ class _RequestDeviceTransferState extends State { _isLoading = false; setState(() {}); if (status >= 200 && status < 300) { - Fluttertoast.showToast( - msg: _subtitle.requestCompleteSuccessfully, - ); + // Fluttertoast.showToast( + // msg: _subtitle.requestCompleteSuccessfully, + // ); Navigator.of(context).pop(); - } else { - String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(errorMessage), - )); } + // else { + // String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle); + // ScaffoldMessenger.of(context).showSnackBar(SnackBar( + // content: Text(errorMessage), + // )); + // } } @override void dispose() { _requestedQuantityController.dispose(); + _deviceTransferProvider.reset(); super.dispose(); } @@ -111,7 +118,7 @@ class _RequestDeviceTransferState extends State { child: Padding( padding: const EdgeInsets.all(8.0), child: Text( - "Transfer Device", + "Transfer Asset", style: Theme.of(context).textTheme.headline5.copyWith(color: Theme.of(context).primaryColor, fontSize: 28, fontWeight: FontWeight.bold), ), ), @@ -131,7 +138,7 @@ class _RequestDeviceTransferState extends State { // }, // ), 12.height, - const ASubTitle("Device"), + const ASubTitle("Asset"), if (_validate && _formModel.device == null) ASubTitle( _subtitle.requiredWord, @@ -142,9 +149,51 @@ class _RequestDeviceTransferState extends State { device: _formModel.device, onDevicePick: (device) { _formModel.device = device; + _formModel.sender.client = device.hospital; + print("device : ${device.hospital.id}"); + print("_formModel : ${_formModel.sender.client.id}"); setState(() {}); }, ), + if (_formModel.device != null) 8.height, + if (_formModel.device != null) const ASubTitle("Asset Site"), + if (_formModel.device != null) + Container( + width: double.infinity, + alignment: Alignment.center, + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16), + decoration: BoxDecoration( + color: AColors.inputFieldBackgroundColor, + border: Border.all( + color: const Color(0xffefefef), + ), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + // boxShadow: const [ + // AppStyle.boxShadow + // ] + ), + child: ASubTitle(_formModel.device?.hospital?.name), + ), + if (_formModel.device != null) 4.height, + if (_formModel.device != null && _formModel.device.destDepartmentName != null) const ASubTitle("Asset Department"), + if (_formModel.device != null && _formModel.device.destDepartmentName != null) + Container( + width: double.infinity, + alignment: Alignment.center, + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16), + decoration: BoxDecoration( + color: AColors.inputFieldBackgroundColor, + border: Border.all( + color: const Color(0xffefefef), + ), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + // boxShadow: const [ + // AppStyle.boxShadow + // ] + ), + child: ASubTitle(_formModel.device.destDepartmentName.toString()), + ), + if (_formModel.device != null) 8.height, // const SizedBox(height: 8,), // const ASubTitle("Sender Department"), // if(_validate && _formModel.senderDepartment == null) @@ -157,36 +206,106 @@ class _RequestDeviceTransferState extends State { // setState(() {}); // }, // ), - 12.height, - const ASubTitle("Destination Client"), - if (_validate && _formModel.receiver.client == null) - ASubTitle( - _subtitle.requiredWord, - color: Colors.red, - ), - 6.height, - HospitalButton( - hospital: _formModel.receiver.client, - onHospitalPick: (hospital) { - _formModel.receiver.client = hospital; + // 12.height, + // const ASubTitle("Destination Client"), + // if (_validate && _formModel.receiver.client == null) + // ASubTitle( + // _subtitle.requiredWord, + // color: Colors.red, + // ), + // 6.height, + // HospitalButton( + // hospital: _formModel.receiver.client, + // onHospitalPick: (hospital) { + // _formModel.receiver.client = hospital; + // setState(() {}); + // }, + // ), + // 12.height, + // const ASubTitle("Destination Department"), + // if (_validate && _formModel.receiver.department == null) + // ASubTitle( + // _subtitle.requiredWord, + // color: Colors.red, + // ), + // 6.height, + // DepartmentButton( + // department: _formModel.receiver.department, + // onDepartmentPick: (department) { + // _formModel.receiver.department = department; + // setState(() {}); + // }, + // ), + const SizedBox( + height: 4, + ), + Divider( + color: Theme.of(context).colorScheme.primary, + ), + const SizedBox(height: 8), + const ASubTitle("Destination"), + const SizedBox( + height: 4, + ), + HospitalAutoCompleteField( + initialValue: _deviceTransferProvider.hospital?.name, + // onSave: (value){ + // _search.hospital = value; + // }, + onSearch: (value) { + _deviceTransferProvider.hospital = value; + _deviceTransferProvider.building = null; + _deviceTransferProvider.floor = null; + _deviceTransferProvider.department = null; + _formModel.receiver.client = value; setState(() {}); }, ), - 12.height, - const ASubTitle("Destination Department"), - if (_validate && _formModel.receiver.department == null) - ASubTitle( - _subtitle.requiredWord, - color: Colors.red, - ), - 6.height, - DepartmentButton( - department: _formModel.receiver.department, - onDepartmentPick: (department) { - _formModel.receiver.department = department; + const SizedBox( + height: 8, + ), + BuildingTypeMenu( + initialValue: _deviceTransferProvider?.building, + building: _deviceTransferProvider?.hospital?.buildings, + onSelect: (status) { + _deviceTransferProvider.building = status; setState(() {}); }, ), + const SizedBox(height: 8), + FloorTypeMenu( + initialValue: _deviceTransferProvider?.floor, + floors: _deviceTransferProvider?.building?.floors, + onSelect: (status) { + _deviceTransferProvider.floor = status; + setState(() {}); + }, + ), + const SizedBox(height: 8), + DepartmentTypeMenu( + initialValue: _deviceTransferProvider?.department, + departments: _deviceTransferProvider?.floor?.departments, + onSelect: (status) { + _deviceTransferProvider.department = status; + _formModel.receiver.department = Department(id: status.id, name: status.name); + setState(() {}); + }, + ), + const SizedBox(height: 8), + const ASubTitle("Room"), + const SizedBox( + height: 4, + ), + ATextFormField( + textAlign: TextAlign.center, + controller: _requestedQuantityController, + style: Theme.of(context).textTheme.subtitle1, + validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only", + textInputType: TextInputType.number, + onSaved: (value) { + _deviceTransferProvider.room = value; + }, + ), 12.height, AButton( text: _subtitle.submit, diff --git a/lib/views/pages/device_transfer/track_device_transfer.dart b/lib/views/pages/device_transfer/track_device_transfer.dart index 454d6d30..1610640c 100644 --- a/lib/views/pages/device_transfer/track_device_transfer.dart +++ b/lib/views/pages/device_transfer/track_device_transfer.dart @@ -1,14 +1,17 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/device_transfer_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; -import 'package:test_sa/models/subtitle.dart'; +import 'package:test_sa/models/device/device_transfer_search.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/device_trancfer/device_transfer_list.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/search/asset_transfer_search_dialog.dart'; + +import '../../widgets/buttons/app_icon_button.dart'; + class TrackDeviceTransferPage extends StatefulWidget { static const String id = "/track-device-transfer"; @@ -18,17 +21,16 @@ class TrackDeviceTransferPage extends StatefulWidget { State createState() => _TrackDeviceTransferPageState(); } -class _TrackDeviceTransferPageState extends State - with TickerProviderStateMixin{ +class _TrackDeviceTransferPageState extends State with TickerProviderStateMixin { DeviceTransferProvider _deviceTransferProvider; UserProvider _userProvider; SettingProvider _settingProvider; + @override Widget build(BuildContext context) { _deviceTransferProvider = Provider.of(context); _userProvider = Provider.of(context); _settingProvider = Provider.of(context); - Subtitle _subtitle = AppLocalization.of(context).subtitle; return Scaffold( body: SafeArea( @@ -48,28 +50,47 @@ class _TrackDeviceTransferPageState extends State Column( children: [ Container( - color:AColors.primaryColor, - padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), + color: AColors.primaryColor, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), child: Column( children: [ Row( children: [ - ABackButton(), + const ABackButton(), Expanded( child: Center( child: Text( - "Device Transfer", - style: Theme.of(context).textTheme.headline6.copyWith( - color: AColors.white, - fontStyle: FontStyle.italic - ), + "Asset Transfer", + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), ), ), ), - const SizedBox(width: 48,) + AIconButton( + iconData: Icons.search, + color: AColors.secondaryColor, + buttonSize: 42, + backgroundColor: AColors.white, + onPressed: () async { + DeviceTransferSearch temp = await showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) { + return AssetTransferSearchDialog(initialSearchValue: _deviceTransferProvider.deviceTransferSearch); + }); + if (temp != null) { + _deviceTransferProvider.deviceTransferSearch = temp; + _deviceTransferProvider.reset(); + setState(() {}); + await _deviceTransferProvider.getRequests( + user: _userProvider.user, + host: _settingProvider.host, + ); + } + }, + ), + const SizedBox(width: 16), ], ), - ], ), ), diff --git a/lib/views/pages/device_transfer/update_device_transfer.dart b/lib/views/pages/device_transfer/update_device_transfer.dart index 2b407a48..1de29ad0 100644 --- a/lib/views/pages/device_transfer/update_device_transfer.dart +++ b/lib/views/pages/device_transfer/update_device_transfer.dart @@ -4,7 +4,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/http_status_manger/http_status_manger.dart'; import 'package:test_sa/controllers/providers/api/device_transfer_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; @@ -20,9 +19,12 @@ import 'package:test_sa/views/widgets/status/gas_refill/gas_status.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; import '../../../../controllers/localization/localization.dart'; +import '../../widgets/timer/app_timer.dart'; + class UpdateDeviceTransfer extends StatefulWidget { final DeviceTransfer model; final bool isSender; + const UpdateDeviceTransfer({Key key, this.model, this.isSender}) : super(key: key); @override @@ -43,56 +45,44 @@ class _UpdateDeviceTransferState extends State { final GlobalKey _scaffoldKey = GlobalKey(); _update() async { + if (_formModel?.timer?.startAt == null) { + await Fluttertoast.showToast(msg: "Working Hours Required"); + return false; + } + if (_formModel?.timer?.endAt == null) { + await Fluttertoast.showToast(msg: "Please Stop The Timer"); + return false; + } _validate = true; - if(!_formKey.currentState.validate()){ + if (!_formKey.currentState.validate()) { setState(() {}); return false; } _formKey.currentState.save(); - _isLoading =true; + _isLoading = true; setState(() {}); int status = await _deviceTransferProvider.updateRequest( - user: _userProvider.user, - host: _settingProvider.host, - requestId: widget.model.id, - isSender: widget.isSender, - newModel: _formModel, - oldModel: widget.model - ); - _isLoading =false; + user: _userProvider.user, host: _settingProvider.host, requestId: widget.model.id, isSender: widget.isSender, newModel: _formModel, oldModel: widget.model); + _isLoading = false; setState(() {}); - if(status >= 200 && status < 300){ + if (status >= 200 && status < 300) { Fluttertoast.showToast( msg: _subtitle.requestCompleteSuccessfully, ); _validate = false; Navigator.of(context).pop(); - Navigator.of(context).pop(); - }else{ - String errorMessage = HttpStatusManger.getStatusMessage( - status: status, subtitle: _subtitle); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - errorMessage - ), - ) - ); } } - @override - void setState(VoidCallback fn){ - if(mounted) super.setState(() {}); - } + // @override + // void setState(VoidCallback fn) { + // if (!mounted) super.setState(() {}); + // } @override void initState() { - _formModel.fromDetails(widget.isSender - ? widget.model.sender : widget.model.receiver, - withSignature: false - ); + _formModel.fromDetails(widget.isSender ? widget.model.sender : widget.model.receiver, withSignature: false); super.initState(); } @@ -107,7 +97,7 @@ class _UpdateDeviceTransferState extends State { _subtitle = AppLocalization.of(context).subtitle; _userProvider = Provider.of(context); _settingProvider = Provider.of(context); - _deviceTransferProvider = Provider.of(context,listen: false); + _deviceTransferProvider = Provider.of(context, listen: false); return Scaffold( key: _scaffoldKey, body: Form( @@ -128,87 +118,93 @@ class _UpdateDeviceTransferState extends State { padding: const EdgeInsets.all(8.0), child: Text( "Edit Transfer Device", - style: Theme.of(context).textTheme.headline5.copyWith( - color: Theme.of(context).primaryColor, - fontSize: 28, - fontWeight: FontWeight.bold - ), + style: Theme.of(context).textTheme.headline5.copyWith(color: Theme.of(context).primaryColor, fontSize: 28, fontWeight: FontWeight.bold), ), ), ), - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), ASubTitle("Comment"), - const SizedBox(height: 4,), + const SizedBox( + height: 4, + ), ATextFormField( initialValue: _formModel?.comment, textAlign: TextAlign.center, style: Theme.of(context).textTheme.subtitle1, textInputType: TextInputType.text, - onSaved: (value){ + onSaved: (value) { _formModel.comment = value; }, ), - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), ASubTitle(_subtitle.travelingHours), - const SizedBox(height: 4,), + const SizedBox( + height: 4, + ), ATextFormField( initialValue: _formModel?.travelingHours, textAlign: TextAlign.center, style: Theme.of(context).textTheme.subtitle1, textInputType: TextInputType.number, - onSaved: (value){ + onSaved: (value) { _formModel.travelingHours = value; }, ), - const SizedBox(height: 8,), + const SizedBox( + height: 16, + ), ASubTitle(_subtitle.workingHours), - const SizedBox(height: 4,), - ATextFormField( - initialValue: _formModel?.workingHours, - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - textInputType: TextInputType.number, - onSaved: (value){ - _formModel.workingHours = value; - }, + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: AppTimer( + timer: _formModel.timer, + onChange: (timer) async { + _formModel.timer = timer; + _formModel.workingHours = (((timer?.durationInSecond ?? 0) / 60) / 60)?.toStringAsFixed(2) ?? "0"; + return true; + }, + ), + ), + ], ), - // const SizedBox(height: 8,), - // const ASubTitle("Sender Department"), - // if(_validate && _formModel.senderDepartment == null) - // ASubTitle(_subtitle.requiredWord,color: Colors.red,), - // const SizedBox(height: 4,), - // DepartmentButton( - // department: _formModel.senderDepartment, - // onDepartmentPick: (department){ - // _formModel.senderDepartment = department; - // setState(() {}); - // }, - // ), - const SizedBox(height: 8,), + const SizedBox(height: 16), ASubTitle(_subtitle.status), - const SizedBox(height: 4,), + const SizedBox( + height: 4, + ), GasStatusMenu( initialValue: _formModel.status, - onSelect: (status){ + onSelect: (status) { + if (status == null) return; _formModel.status = status; setState(() {}); }, ), - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), const ASubTitle("Signature"), // if(_validate && _formModel.signature == null) // ASubTitle(_subtitle.requiredWord,color: Colors.red,), - const SizedBox(height: 4,), + const SizedBox( + height: 4, + ), ESignature( - oldSignature: widget.isSender - ? widget.model.sender.signature - : widget.model.receiver.signature, - newSignature: _signature, - onSaved: (signature){ - _signature = signature; - _formModel.signature = base64Encode(signature); - }, + oldSignature: widget.isSender ? widget.model.sender.signature : widget.model.receiver.signature, + newSignature: _signature, + onSaved: (signature) { + _signature = signature; + if (signature == null || signature.isEmpty) return; + _formModel.signature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + // base64Encode(signature); + }, ), Padding( padding: const EdgeInsets.all(16.0), @@ -217,7 +213,9 @@ class _UpdateDeviceTransferState extends State { onPressed: _update, ), ), - const SizedBox(height: 100,) + const SizedBox( + height: 100, + ) ], ), ), @@ -227,4 +225,3 @@ class _UpdateDeviceTransferState extends State { ); } } - diff --git a/lib/views/pages/login.dart b/lib/views/pages/login.dart index 33372b50..a6fba23d 100644 --- a/lib/views/pages/login.dart +++ b/lib/views/pages/login.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/http_status_manger/http_status_manger.dart'; +import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; @@ -9,14 +9,11 @@ import 'package:test_sa/controllers/validator/validator.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/models/user.dart'; import 'package:test_sa/views/app_style/sizing.dart'; -import 'package:test_sa/views/pages/register.dart'; import 'package:test_sa/views/pages/user/land_page.dart'; import 'package:test_sa/views/widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; -import '../widgets/buttons/app_outlined_button.dart'; - class Login extends StatefulWidget { static final String id = "/login"; @@ -118,13 +115,22 @@ class _LoginState extends State { host: _settingProvider.host, ); if (status >= 200 && status < 300) { - _settingProvider.setUser(_userProvider.user); - if (_userProvider.user.isActive) + if (_userProvider.user.isAuthenticated ?? false) { + _settingProvider.setUser(_userProvider.user); Navigator.of(context).pushNamed(LandPage.id); - else - Fluttertoast.showToast(msg: _subtitle.activationAlert); + } else { + Fluttertoast.showToast(msg: _userProvider.user.message); + } + + // if (_userProvider.user.isActive) + + // else + // Fluttertoast.showToast(msg: _subtitle.activationAlert); } else { - String errorMessage = status == 400 ? _subtitle.wrongEmailOrPassword : HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle); + if (status >= 400 && status < 500) return; + + String errorMessage = + status == 400 || _userProvider.user?.userName == null ? _subtitle.wrongEmailOrPassword : HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle); ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(errorMessage), )); diff --git a/lib/views/pages/register.dart b/lib/views/pages/register.dart index af5f83cd..1246fff3 100644 --- a/lib/views/pages/register.dart +++ b/lib/views/pages/register.dart @@ -1,18 +1,17 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/http_status_manger/http_status_manger.dart'; +import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/controllers/validator/validator.dart'; +import 'package:test_sa/models/hospital.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/models/user.dart'; import 'package:test_sa/views/widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; -import 'package:test_sa/views/widgets/departments/department_button.dart'; import 'package:test_sa/views/widgets/hospitals/hospital_button.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; @@ -123,20 +122,22 @@ class _RegisterState extends State { ), const SizedBox(height: 12), HospitalButton( - hospital: _user.hospital, + hospital: Hospital(id: _user.clientId, name: _user.clientName), onHospitalPick: (hospital) { - _user.hospital = hospital; - setState(() {}); - }, - ), - const SizedBox(height: 12), - DepartmentButton( - department: _user.department, - onDepartmentPick: (department) { - _user.department = department; + _user.clientId = hospital.id; + _user.clientName = hospital.name; setState(() {}); }, ), + // const SizedBox(height: 12), + // DepartmentButton( + // department: Department(id: _user.departmentId, name: _user.departmentName), + // onDepartmentPick: (department) { + // _user.departmentId = department.id; + // _user.departmentName = department.name; + // setState(() {}); + // }, + // ), const SizedBox(height: 12), ATextFormField( initialValue: _user.phoneNumber, @@ -150,31 +151,31 @@ class _RegisterState extends State { }, ), SizedBox(height: 8), - ATextFormField( - initialValue: _user.whatsApp, - hintText: _subtitle.whatsApp, - style: Theme.of(context).textTheme.headline6, - prefixIconData: FontAwesomeIcons.whatsapp, - prefixIconSize: 36, - validator: (value) => Validator.isPhoneNumber(value) ? null : _subtitle.phoneNumberValidateMessage, - textInputType: TextInputType.phone, - onSaved: (value) { - _user.whatsApp = value; - }, - ), + // ATextFormField( + // initialValue: _user.whatsApp, + // hintText: _subtitle.whatsApp, + // style: Theme.of(context).textTheme.headline6, + // prefixIconData: FontAwesomeIcons.whatsapp, + // prefixIconSize: 36, + // validator: (value) => Validator.isPhoneNumber(value) ? null : _subtitle.phoneNumberValidateMessage, + // textInputType: TextInputType.phone, + // onSaved: (value) { + // _user.whatsApp = value; + // }, + // ), const SizedBox(height: 12), AButton( text: _subtitle.signUp, onPressed: () async { if (!_formKey.currentState.validate()) return; _formKey.currentState.save(); - if (_user.hospital == null) { + if (_user.clientId == null) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(_subtitle.hospitalRequired), )); return; } - if (_user.department == null) { + if (_user.departmentId == null) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(_subtitle.unitRequired), )); diff --git a/lib/views/pages/splash_screen.dart b/lib/views/pages/splash_screen.dart index a7bfa347..e28c09de 100644 --- a/lib/views/pages/splash_screen.dart +++ b/lib/views/pages/splash_screen.dart @@ -1,7 +1,6 @@ import 'dart:convert'; import 'package:firebase_core/firebase_core.dart'; -import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flare_flutter/flare_actor.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -23,53 +22,45 @@ class SplashScreen extends StatefulWidget { } class _SplashScreenState extends State { - SettingProvider _settingProvider; UserProvider _userProvider; - _goToUserScreen(User user){ - _userProvider.user = user; - // Navigator.of(context).pushNamed(Login.id); - Navigator.of(context).pushNamed(LandPage.id); + _goToUserScreen(User user) { + if (user.tokenlife != null && (DateTime.tryParse(user.tokenlife)?.isAfter(DateTime.now()) ?? false)) { + _userProvider.user = user; + // Navigator.of(context).pushNamed(Login.id); + Navigator.of(context).pushNamed(LandPage.id); + } } @override void initState() { Firebase.initializeApp(); - NotificationManger.initialisation( - (notificationDetails) { - AppNotification notification = AppNotification.fromJson(json.decode(notificationDetails.payload)); - if(notification.path == null || notification.path.isEmpty) - return; - Navigator.pushNamed( - context, - notification.path, - arguments: notification.requestId - ); - } - , (id, title, body, payload) async { - }); + NotificationManger.initialisation((notificationDetails) { + AppNotification notification = AppNotification.fromJson(json.decode(notificationDetails.payload)); + if (notification.path == null || notification.path.isEmpty) return; + Navigator.pushNamed(context, notification.path, arguments: notification.requestId); + }, (id, title, body, payload) async {}); super.initState(); } @override Widget build(BuildContext context) { - _settingProvider = Provider.of(context,listen: false); - _userProvider = Provider.of(context,listen: false); + _settingProvider = Provider.of(context, listen: false); + _userProvider = Provider.of(context, listen: false); return Scaffold( backgroundColor: Colors.white, body: Center( child: SizedBox( - width: MediaQuery.of(context).size.width/1.1, - child: FlareActor( + width: MediaQuery.of(context).size.width / 1.1, + child: FlareActor( "assets/rives/atoms_splash.flr", fit: BoxFit.contain, animation: "splash", callback: (animation) async { - print(await FirebaseMessaging.instance.getToken()); Navigator.of(context).pushNamed(Login.id); - if(_settingProvider.isLoaded && _settingProvider.user != null){ + if (_settingProvider.isLoaded && _settingProvider.user != null) { _goToUserScreen(_settingProvider.user); } }, diff --git a/lib/views/pages/sub_workorder/create_sub_workorder_page.dart b/lib/views/pages/sub_workorder/create_sub_workorder_page.dart new file mode 100644 index 00000000..fdfd67e5 --- /dev/null +++ b/lib/views/pages/sub_workorder/create_sub_workorder_page.dart @@ -0,0 +1,363 @@ +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_types_provider.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/call_request_for_work_order_model.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/service_report.dart'; +import 'package:test_sa/models/service_request/search_work_order.dart'; +import 'package:test_sa/views/app_style/colors.dart'; +import 'package:test_sa/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart'; +import 'package:test_sa/views/pages/sub_workorder/work_order_details_bottom_sheet.dart'; +import 'package:test_sa/views/pages/sub_workorder/workorder_details.dart'; +import 'package:test_sa/views/widgets/loaders/app_loading.dart'; +import 'package:test_sa/views/widgets/status/service_request/service_request_defect_types_mune.dart'; + +import '../../../controllers/api_routes/http_status_manger.dart'; +import '../../../controllers/localization/localization.dart'; +import '../../../controllers/providers/api/status_drop_down/report/service_report_fault_description_provider.dart'; +import '../../../models/subtitle.dart'; +import '../../widgets/app_text_form_field.dart'; +import '../../widgets/buttons/app_back_button.dart'; +import '../../widgets/buttons/app_button.dart'; +import '../../widgets/date_and_time/date_picker.dart'; +import '../../widgets/images/mini_one_image_picker.dart'; +import '../../widgets/status/report/service_report_fault_description.dart'; +import '../../widgets/status/report/service_report_reasons.dart'; +import '../../widgets/titles/app_sub_title.dart'; + +class CreateSubWorkOrderPage extends StatefulWidget { + static const id = "/CreateSubWorkOrder"; + final SearchWorkOrder workOrder; + + const CreateSubWorkOrderPage({this.workOrder, Key key}) : super(key: key); + + @override + State createState() => _CreateSubWorkOrderPageState(); +} + +class _CreateSubWorkOrderPageState extends State { + final GlobalKey _formKey = GlobalKey(); + SearchWorkOrder _subWorkOrders; + Lookup _serviceReportReason = const Lookup(); + ServiceReport _serviceReport; + File _image; + bool _isLoading = false; + bool _validate = false; + + @override + void initState() { + _subWorkOrders = SearchWorkOrder( + assignedEmployee: widget?.workOrder?.callRequest?.assignedEmployee, + callRequest: CallRequest(id: widget?.workOrder?.callRequest?.id), + currentSituation: null, + supplier: null, + ); + _serviceReport = ServiceReport(id: widget.workOrder.id, type: widget.workOrder.assetType, equipmentStatus: widget.workOrder.equipmentStatus); + _isLoading = true; + super.initState(); + } + + var assetTypesProvider; + CallRequestForWorkOrder _callRequestForWorkOrder; + + Future getAssetType() async { + //if (assetTypesProvider == null) { + Provider.of(context, listen: false).reset(); + assetTypesProvider = Provider.of(context, listen: false); + _callRequestForWorkOrder = await Provider.of(context).getCallRequestForWorkOrder(callId: widget.workOrder.callRequest.id.toString()); + await assetTypesProvider.getTypes(); + _subWorkOrders?.assetType = assetTypesProvider.statuses?.firstWhere( + (element) => element.value == _callRequestForWorkOrder?.assetType, + orElse: () => null, + ); + setState(() { + _isLoading = false; + }); + //} + } + + @override + Widget build(BuildContext context) { + if (_callRequestForWorkOrder == null) { + getAssetType(); + } + final Subtitle subtitle = AppLocalization.of(context).subtitle; + + return Scaffold( + body: SafeArea( + child: _isLoading + ? const ALoading() + : Column( + children: [ + SingleChildScrollView( + child: Form( + key: _formKey, + child: Column( + children: [ + Container( + color: AColors.primaryColor, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), + child: Column( + children: [ + Row( + children: [ + const ABackButton(), + Expanded( + child: Center( + child: Text( + "New Work Order", + style: Theme.of(context).textTheme.titleLarge.copyWith(color: AColors.white, fontStyle: FontStyle.italic), + ), + ), + ), + const SizedBox( + width: 48, + ) + ], + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16), + child: Column( + children: [ + WorkOrderDetails(item: widget.workOrder, assetType: _subWorkOrders?.assetType), + const SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ASubTitle("Equipment status"), + if (_validate && _subWorkOrders?.equipmentStatus == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), + ServiceRequestDefectTypesMenu( + initialValue: _serviceReport.equipmentStatus, + onSelect: (status) { + _subWorkOrders.equipmentStatus = status; + _serviceReport.equipmentStatus = status; + setState(() {}); + }, + ), + ], + ), + const SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ASubTitle("Return to Service"), + if (_validate && _subWorkOrders.visitDate == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), + Row( + children: [ + Expanded( + child: ADatePicker( + date: DateTime.tryParse(_subWorkOrders.visitDate ?? ""), + from: DateTime(1950), + onDatePicker: (date) { + _subWorkOrders.visitDate = date?.toIso8601String(); + setState(() {}); + }, + ), + ), + ], + ), + ], + ), + const SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle("Failure ${subtitle.reasons}"), + if (_validate && _subWorkOrders.reason == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), + ServiceReportReasonsMenu( + initialValue: _serviceReportReason, + onSelect: (status) { + _serviceReportReason = status; + _subWorkOrders.reason = status; + setState(() {}); + }, + ), + ], + ), + const SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(subtitle.faultDescription), + if (_validate && _subWorkOrders.faultDescription == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), + ServiceReportFaultDescription( + requestId: widget.workOrder?.callRequest?.id?.toString(), + initialValue: _subWorkOrders?.faultDescription, + onSelect: (status) { + _subWorkOrders.faultDescription = status; + if (mounted) setState(() {}); + }, + ), + ], + ), + const SizedBox(height: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ASubTitle("Solution"), + const SizedBox(height: 4), + ATextFormField(labelText: _subWorkOrders?.faultDescription?.workPerformed ?? "", textInputType: TextInputType.multiline, enable: false), + ], + ), + const SizedBox(height: 8), + InkWell( + onTap: () async { + await showModalBottomSheet( + context: context, + useSafeArea: true, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => WorkOrderDetailsBottomSheet(subWorkOrder: _subWorkOrders), + ); + log(_subWorkOrders?.toJson()?.toString()); + }, + child: Card( + child: ListTile( + title: Row( + children: [ + Text( + "WO Details", + style: Theme.of(context).textTheme.bodyMedium, + ), + const Text("*", style: TextStyle(color: Colors.red)), + ], + ), + trailing: const Icon(Icons.arrow_forward_ios, size: 14, color: AColors.primaryColor), + ), + ), + ), + const SizedBox(height: 8), + InkWell( + onTap: () async { + await showModalBottomSheet( + context: context, + useSafeArea: true, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => SparePartsBottomSheet(subWorkOrder: _subWorkOrders), + ); + log(_subWorkOrders?.toJson()?.toString()); + }, + child: Card( + child: ListTile( + title: Row( + children: [ + Text( + "Spare Parts", + style: Theme.of(context).textTheme.bodyMedium, + ), + const Text("*", style: TextStyle(color: Colors.red)), + ], + ), + trailing: const Icon(Icons.arrow_forward_ios, size: 14, color: AColors.primaryColor), + ), + ), + ), + const SizedBox(height: 8), + AMiniOneImagePicker( + image: _image, + onPick: (image) { + _image = image; + _subWorkOrders.attachmentsWorkOrder ??= []; + _subWorkOrders.attachmentsWorkOrder.add(AttachmentsWorkOrder(name: "${image.path.split("/").last}|${base64Encode(image.readAsBytesSync())}")); + }, + ), + const SizedBox(height: 50), + ], + ), + ), + ], + ), + ), + ).expanded, + Padding( + padding: const EdgeInsets.all(16.0), + child: AButton( + text: subtitle.create, + onPressed: () async { + _subWorkOrders.parentWOId = widget.workOrder.id; + _validate = true; + setState(() {}); + if (validate()) { + if (_subWorkOrders.timer?.startAt == null || _subWorkOrders.timer?.endAt == null) { + Fluttertoast.showToast(msg: "Working hours required"); + return; + } else if (_subWorkOrders.calllastSituation == null) { + Fluttertoast.showToast(msg: "${subtitle.callLastSituation} required"); + return; + } + _validate = false; + _isLoading = true; + setState(() {}); + if (_formKey.currentState?.validate() ?? false) {} + _formKey.currentState?.save(); + final serviceRequestsProvider = Provider.of(context, listen: false); + final status = await serviceRequestsProvider.createSubWorkOrder(workOrder: _subWorkOrders); + _isLoading = false; + setState(() {}); + if (status >= 200 && status < 300) { + Fluttertoast.showToast(msg: subtitle.requestCompleteSuccessfully); + Navigator.of(context).pop(); + Navigator.of(context).pop(); + } else { + String errorMessage = HttpStatusManger.getStatusMessage(status: serviceRequestsProvider.stateCode, subtitle: subtitle); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(errorMessage), + )); + } + } + }, + ), + ), + ], + ), + ), + ); + } + + bool validate() { + if (_subWorkOrders.faultDescription == null || _subWorkOrders.reason == null || _subWorkOrders.equipmentStatus == null || _subWorkOrders.visitDate == null) { + return false; + } else { + return true; + } + } +} diff --git a/lib/views/pages/sub_workorder/search_sub_workorder_page.dart b/lib/views/pages/sub_workorder/search_sub_workorder_page.dart new file mode 100644 index 00000000..35817468 --- /dev/null +++ b/lib/views/pages/sub_workorder/search_sub_workorder_page.dart @@ -0,0 +1,224 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; +import 'package:test_sa/models/engineer.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/service_request/search_work_order.dart'; +import 'package:test_sa/models/subtitle.dart'; +import 'package:test_sa/views/pages/sub_workorder/workorder_list.dart'; +import 'package:test_sa/views/widgets/app_text_form_field.dart'; +import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; +import 'package:test_sa/views/widgets/hospitals/hospital_auto_complete_field_new.dart'; + +import '../../../controllers/api_routes/http_status_manger.dart'; +import '../../../controllers/localization/localization.dart'; +import '../../../controllers/providers/api/status_drop_down/report/service_report_maintenance_situation_provider.dart'; +import '../../app_style/colors.dart'; +import '../../widgets/buttons/app_back_button.dart'; +import '../../widgets/buttons/app_button.dart'; +import '../../widgets/status/report/service_report_all_users.dart'; +import '../../widgets/status/report/service_report_maintenance_situation.dart'; +import '../../widgets/status/report/service_report_visit_date_operator.dart'; +import '../../widgets/titles/app_sub_title.dart'; + +class SearchSubWorkOrderPage extends StatefulWidget { + static String id = "/SubWorkOrderPage"; + + const SearchSubWorkOrderPage({Key key}) : super(key: key); + + @override + State createState() => _SearchSubWorkOrderPageState(); +} + +class _SearchSubWorkOrderPageState extends State { + final GlobalKey _formKey = GlobalKey(); + final SearchWorkOrder _searchWorkOrders = SearchWorkOrder(); + Subtitle _subtitle; + bool _isLoading = false; + String _callerId = "", _site = ""; + Lookup _dateOperator; + + @override + void initState() { + super.initState(); + if (context.mounted) { + Provider.of(context, listen: false).reset(); + } + } + + @override + Widget build(BuildContext context) { + _subtitle = AppLocalization.of(context).subtitle; + return Scaffold( + body: SafeArea( + child: SingleChildScrollView( + child: Column( + children: [ + Container( + color: AColors.primaryColor, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), + child: Column( + children: [ + Row( + children: [ + const ABackButton(), + Expanded( + child: Center( + child: Text( + "Search Work Order", + style: Theme.of(context).textTheme.titleLarge.copyWith(color: AColors.white, fontStyle: FontStyle.italic), + ), + ), + ), + const SizedBox( + width: 48, + ) + ], + ), + ], + ), + ), + const SizedBox(height: 8), + Form( + key: _formKey, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ATextFormField( + labelText: "Call ID", + onSaved: (value) { + _callerId = value; + }, + ), + const SizedBox(height: 16), + ATextFormField( + labelText: "Asset S.N.", + textInputType: TextInputType.number, + onSaved: (value) { + if (value != null) { + _searchWorkOrders.assetType = Lookup(name: value); + } + }, + ), + const SizedBox(height: 16), + ATextFormField( + labelText: "Work Order No.", + onSaved: (value) { + _searchWorkOrders.workOrderNo = value; + }, + ), + const SizedBox(height: 16), + ASubTitle(_subtitle.assignedEmployee), + const SizedBox(height: 4), + ServiceReportAllUsers( + initialValue: _searchWorkOrders.assignedEmployee == null ? null : Engineer(id: _searchWorkOrders.assignedEmployee.id, name: _searchWorkOrders.assignedEmployee.name), + onSelect: (engineer) { + _searchWorkOrders.assignedEmployee = AssignedEmployee(id: engineer.id, name: engineer.name); + }, + ), + const SizedBox(height: 16), + const ASubTitle("Maintenance Situation"), + const SizedBox(height: 4), + ServiceReportMaintenanceSituation( + initialValue: _searchWorkOrders.calllastSituation, + onSelect: (status) { + if (status?.value == 12 || _searchWorkOrders.calllastSituation?.value == 12) { + _searchWorkOrders.calllastSituation = status; + setState(() {}); + } else { + _searchWorkOrders.calllastSituation = status; + } + }, + woId: _searchWorkOrders.id?.toString(), + ), + const SizedBox(height: 16), + HospitalAutoCompleteField( + initialValue: _site, + onSearch: (value) { + _site = value.name; + setState(() {}); + }, + ), + const SizedBox(height: 16), + ASubTitle(_subtitle.visitDate), + const SizedBox(height: 4), + ServiceReportVisitDateOperator( + initialValue: _dateOperator, + onSelect: (status) { + _dateOperator = status; + }, + ), + Row( + children: [ + Expanded( + child: ADatePicker( + date: DateTime.tryParse(_searchWorkOrders.visitDate ?? ""), + from: DateTime(1950), + onDatePicker: (date) { + _searchWorkOrders.visitDate = date?.toIso8601String(); + setState(() {}); + }, + ), + ), + ], + ), + ], + ), + ), + ), + const SizedBox(height: 100), + ], + ), + ), + ), + floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, + floatingActionButton: _isLoading + ? const CircularProgressIndicator() + : Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: AButton( + text: _subtitle.search, + onPressed: () async { + _isLoading = true; + setState(() {}); + if (_formKey.currentState?.validate() ?? false) {} + _formKey.currentState?.save(); + final serviceRequestsProvider = Provider.of(context, listen: false); + serviceRequestsProvider.reset(); + final List woList = await serviceRequestsProvider.searchForWorkOrders( + _searchWorkOrders, + _callerId, + _dateOperator, + _site, + ); + _isLoading = false; + setState(() {}); + if (serviceRequestsProvider.stateCode >= 200 && serviceRequestsProvider.stateCode < 300) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => WorkOrderList( + items: woList, + onLazyLoading: () async { + return await serviceRequestsProvider.searchForWorkOrders( + _searchWorkOrders, + _callerId, + _dateOperator, + _site, + ); + }, + ), + ), + ); + } else { + String errorMessage = HttpStatusManger.getStatusMessage(status: serviceRequestsProvider.stateCode, subtitle: _subtitle); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(errorMessage))); + } + }, + ), + ), + ); + } +} diff --git a/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart b/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart new file mode 100644 index 00000000..9cb43482 --- /dev/null +++ b/lib/views/pages/sub_workorder/spare_parts_details_bottom_sheet.dart @@ -0,0 +1,174 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/models/part.dart'; +import 'package:test_sa/models/service_request/search_work_order.dart'; +import 'package:test_sa/views/app_style/colors.dart'; + +import '../../../controllers/localization/localization.dart'; +import '../../../models/subtitle.dart'; +import '../../app_style/sizing.dart'; +import '../../widgets/buttons/app_button.dart'; +import '../../widgets/parts/auto_complete_parts_field.dart'; +import '../../widgets/parts/part_item.dart'; +import '../../widgets/titles/app_sub_title.dart'; + +class SparePartsBottomSheet extends StatefulWidget { + final SearchWorkOrder subWorkOrder; + + const SparePartsBottomSheet({this.subWorkOrder, Key key}) : super(key: key); + + @override + State createState() => _SparePartsBottomSheetState(); +} + +class _SparePartsBottomSheetState extends State { + final GlobalKey _formKey = GlobalKey(); + final SearchWorkOrder _workOrder = SearchWorkOrder(); + bool _validate = false; + + @override + void initState() { + super.initState(); + _workOrder.copyFrom(widget.subWorkOrder); + } + + @override + void dispose() { + _workOrder.sparePartsWorkOrders = widget.subWorkOrder.sparePartsWorkOrders; + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final Subtitle subtitle = AppLocalization.of(context).subtitle; + return Padding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + child: ClipRRect( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(15), + topRight: Radius.circular(15), + ), + clipBehavior: Clip.antiAliasWithSaveLayer, + child: Container( + color: Colors.white, + height: size.height * 0.9, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ASubTitle("Spare Parts"), + const SizedBox(height: 8), + Expanded( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 16), + decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: const [ + BoxShadow( + color: AColors.grey, + offset: Offset(0, -1), + ) + ]), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + Expanded( + flex: 3, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(subtitle.partNumberName), + _validate && _workOrder.sparePartsWorkOrders == null + ? ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + const SizedBox(height: 4), + AutoCompletePartsField( + onPick: (part) { + _workOrder.sparePartsWorkOrders ??= []; + _workOrder.sparePartsWorkOrders.add(SparePartsWorkOrders( + id: part.reportPartID, + qty: part.quantity, + sparePart: SparePart(id: part.id, partName: part.name, partNo: part.code), + )); + }, + ), + ], + ), + ), + ], + ), + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), + ), + if (_workOrder.sparePartsWorkOrders?.isNotEmpty ?? false) + Row( + children: [ + Expanded(flex: 3, child: Text(subtitle.number)), + Expanded(flex: 1, child: Text(subtitle.quantity)), + ], + ), + if (_workOrder.sparePartsWorkOrders?.isNotEmpty ?? false) + Column( + children: List.generate( + _workOrder.sparePartsWorkOrders?.length, + (index) { + final spare = _workOrder.sparePartsWorkOrders[index]; + Part part = Part( + id: spare.sparePart?.id, + reportPartID: spare.id, + code: spare.sparePart?.partNo, + name: spare.sparePart?.partName, + quantity: spare.qty, + ); + return PartItem( + part: part, + onEdit: (qty) { + spare.qty = qty; + }, + onDelete: (part) { + _workOrder.sparePartsWorkOrders.remove(spare); + setState(() {}); + }, + ); + }, + ), + ), + const SizedBox(height: 16), + ], + ), + ), + const SizedBox(height: 24), + ], + ), + ), + ), + ), + AButton( + text: subtitle.submit, + onPressed: () async { + _formKey.currentState.save(); + widget.subWorkOrder.copyFrom(_workOrder); + Navigator.pop(context); + }, + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart b/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart new file mode 100644 index 00000000..e91de02e --- /dev/null +++ b/lib/views/pages/sub_workorder/work_order_details_bottom_sheet.dart @@ -0,0 +1,173 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/models/service_request/search_work_order.dart'; +import 'package:test_sa/models/subtitle.dart'; +import 'package:test_sa/views/widgets/app_text_form_field.dart'; +import 'package:test_sa/views/widgets/buttons/app_button.dart'; +import 'package:test_sa/views/widgets/status/report/service_report_assistant_employee_menu.dart'; +import 'package:test_sa/views/widgets/status/report/service_report_maintenance_situation.dart'; +import 'package:test_sa/views/widgets/status/report/service_report_repair_location.dart'; + +import '../../../controllers/localization/localization.dart'; +import '../../../controllers/providers/api/status_drop_down/report/service_report_maintenance_situation_provider.dart'; +import '../../widgets/timer/app_timer.dart'; +import '../../widgets/titles/app_sub_title.dart'; + +class WorkOrderDetailsBottomSheet extends StatefulWidget { + final SearchWorkOrder subWorkOrder; + const WorkOrderDetailsBottomSheet({this.subWorkOrder, Key key}) : super(key: key); + + @override + State createState() => _WorkOrderDetailsBottomSheetState(); +} + +class _WorkOrderDetailsBottomSheetState extends State { + final GlobalKey _formKey = GlobalKey(); + final SearchWorkOrder _workOrder = SearchWorkOrder(); + + @override + void initState() { + super.initState(); + + _workOrder.copyFrom(widget.subWorkOrder); + if (context.mounted) { + Provider.of(context, listen: false).reset(); + } + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + final Subtitle subtitle = AppLocalization.of(context).subtitle; + return Padding( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + child: ClipRRect( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(15), + topRight: Radius.circular(15), + ), + clipBehavior: Clip.antiAliasWithSaveLayer, + child: Container( + color: Colors.white, + height: size.height * 0.9, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20), + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ASubTitle("WO Details"), + const SizedBox(height: 8), + Expanded( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 8), + ATextFormField(enable: false, hintText: "Assigned Employee: ${_workOrder.assignedEmployee?.name}"), + const SizedBox(height: 8), + const ASubTitle("Assistant Employee"), + const SizedBox(height: 4), + ServiceReportAssistantEmployeeMenu( + initialValue: (_workOrder.assistantEmployees?.isNotEmpty ?? false) ? _workOrder.assistantEmployees?.first : null, + onSelect: (assistantsEmployee) { + _workOrder.assistantEmployees = [assistantsEmployee]; + }, + ), + const SizedBox(height: 8), + ASubTitle(subtitle.workingHours), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: AppTimer( + timer: _workOrder.timer, + onChange: (timer) async { + _workOrder.timer = timer; + _workOrder.workingHours = num.tryParse((((timer?.durationInSecond ?? 0) / 60) / 60)?.toStringAsFixed(2) ?? "0"); + return true; + }, + ), + ), + ], + ), + const SizedBox(height: 16), + ATextFormField( + labelText: "Travel Hours", + initialValue: _workOrder.travelingHours?.toString(), + textInputType: TextInputType.number, + onSaved: (value) { + _workOrder.travelingHours = num.tryParse(value); + }, + ), + const SizedBox(height: 8), + ATextFormField( + labelText: "Travel Expense", + initialValue: _workOrder.travelingExpenses?.toString(), + textInputType: TextInputType.number, + onSaved: (value) { + _workOrder.travelingExpenses = num.tryParse(value); + }, + ), + const SizedBox(height: 8), + ASubTitle(subtitle.callLastSituation), + const SizedBox(height: 4), + ServiceReportMaintenanceSituation( + initialValue: _workOrder.calllastSituation, + onSelect: (status) { + if (status?.value == 12 || _workOrder.calllastSituation?.value == 12) { + _workOrder.calllastSituation = status; + setState(() {}); + } else { + _workOrder.calllastSituation = status; + } + }, + woId: widget.subWorkOrder?.callRequest?.id?.toString(), + ), + const SizedBox(height: 8), + const ASubTitle("Repair Location"), + const SizedBox(height: 4), + ServiceReportRepairLocation( + initialValue: _workOrder.repairLocation, + onSelect: (status) { + _workOrder.repairLocation = status; + }, + ), + const SizedBox(height: 8), + ATextFormField( + labelText: "Technical Comments", + initialValue: _workOrder.comment, + textInputType: TextInputType.multiline, + onSaved: (value) { + _workOrder.comment = value; + }, + ), + const SizedBox(height: 24), + ], + ), + ), + ), + ), + AButton( + text: subtitle.submit, + onPressed: () async { + if (_workOrder?.workingHours == null) { + await Fluttertoast.showToast(msg: "Working Hours Timer Isn't Started"); + return; + } + _formKey.currentState.save(); + widget.subWorkOrder.copyFrom(_workOrder); + Navigator.pop(context); + }, + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/views/pages/sub_workorder/workorder_details.dart b/lib/views/pages/sub_workorder/workorder_details.dart new file mode 100644 index 00000000..6383f586 --- /dev/null +++ b/lib/views/pages/sub_workorder/workorder_details.dart @@ -0,0 +1,81 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/models/lookup.dart'; + +import '../../../controllers/localization/localization.dart'; +import '../../../models/service_request/search_work_order.dart'; +import '../../../models/subtitle.dart'; +import '../../app_style/colors.dart'; +import '../../app_style/sizing.dart'; + +class WorkOrderDetails extends StatelessWidget { + final SearchWorkOrder item; + Lookup assetType; + + WorkOrderDetails({@required this.item, this.assetType, Key key}) : super(key: key); + Subtitle _subtitle; + + @override + Widget build(BuildContext context) { + _subtitle = AppLocalization.of(context).subtitle; + return Column( + children: [ + Container( + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + color: AColors.inputFieldBackgroundColor, + border: Border.all( + color: Color(0xffefefef), + ), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + // boxShadow: const [ + // AppStyle.boxShadow + // ] + ), + child: Column( + children: [ + _buildRow(_subtitle.callId, item.callRequest?.id?.toString() ?? "", context), + _buildRow(_subtitle.assetNumber, item.callRequest?.asset?.assetNumber ?? "", context), + _buildRow("WO No", item.workOrderNo, context), + _buildRow(_subtitle.assetName, item.callRequest?.asset?.assetNumber ?? '', context), + _buildRow(_subtitle.department, item.callRequest?.asset?.department ?? '', context), + _buildRow(_subtitle.assetSN, item.callRequest?.asset?.assetSerialNo ?? '', context), + _buildRow(_subtitle.model, item.callRequest?.asset?.modelDefinition?.modelName ?? "", context), + _buildRow("Manufacturer", item.callRequest?.asset?.modelDefinition?.manufacturerName ?? "", context), + _buildRow(_subtitle.site, item.callRequest?.asset?.site?.custName ?? "", context), + ], + ), + ), + const SizedBox(height: 8), + Container( + padding: EdgeInsets.all(10), + height: 55, + decoration: BoxDecoration( + color: AColors.inputFieldBackgroundColor, + border: Border.all( + color: Color(0xffefefef), + ), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + ), + child: _buildRow("Asset Type", assetType?.name ?? (item.assetType?.name ?? ""), context), + ) + ], + ); + } + + Widget _buildRow(String title, String value, BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + title + " : ", + style: Theme.of(context).textTheme.subtitle2.copyWith(fontWeight: FontWeight.bold), + ), + //if (item.clientName != null) + Text( + value, + style: Theme.of(context).textTheme.subtitle2.copyWith(), + ), + ], + ); + } +} diff --git a/lib/views/pages/sub_workorder/workorder_item.dart b/lib/views/pages/sub_workorder/workorder_item.dart new file mode 100644 index 00000000..e18f773a --- /dev/null +++ b/lib/views/pages/sub_workorder/workorder_item.dart @@ -0,0 +1,106 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/controllers/localization/localization.dart'; +import 'package:test_sa/models/subtitle.dart'; +import 'package:test_sa/views/app_style/colors.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; +import 'package:test_sa/views/widgets/requests/request_status.dart'; + +import '../../../models/service_request/search_work_order.dart'; + +class WorkOrderItem extends StatelessWidget { + final int index; + final SearchWorkOrder item; + final Function(SearchWorkOrder) onPressed; + + const WorkOrderItem({Key key, this.item, this.onPressed, this.index}) : super(key: key); + + @override + Widget build(BuildContext context) { + Subtitle _subtitle = AppLocalization.of(context).subtitle; + Color itemColor = index % 2 == 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; + Color onItemColor = index % 2 != 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: ElevatedButton( + style: ElevatedButton.styleFrom( + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8), + backgroundColor: itemColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), + ), + ), + onPressed: () { + onPressed(item); + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + item.callRequest.callNo ?? "-----", + style: Theme.of(context).textTheme.headline6.copyWith(color: onItemColor, fontSize: 16, fontWeight: FontWeight.bold), + ), + Text( + item.callRequest.asset.id.toString(), + style: Theme.of(context).textTheme.subtitle2.copyWith( + color: onItemColor, + ), + ), + Row( + children: [ + Expanded( + child: Text( + _subtitle.assetName, + style: Theme.of(context).textTheme.subtitle2.copyWith( + color: onItemColor, + ), + ), + ), + //if (item.clientName != null) + Text( + item.callRequest.asset.assetNumber, + style: Theme.of(context).textTheme.subtitle2.copyWith( + color: onItemColor, + ), + ), + ], + ), + Text( + item.calllastSituation.name, + style: Theme.of(context).textTheme.subtitle2.copyWith( + color: onItemColor, + ), + ), + Divider( + color: onItemColor, + ), + Row( + children: [ + Expanded( + child: Text( + _subtitle.status, + style: Theme.of(context).textTheme.subtitle2.copyWith( + color: onItemColor, + ), + ), + ), + if (item.callRequest.status?.id != null) StatusLabel(label: item.callRequest.status.name, color: AColors.getGasStatusColor(item.callRequest.status.id)), + ], + ), + ], + ), + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/views/pages/sub_workorder/workorder_list.dart b/lib/views/pages/sub_workorder/workorder_list.dart new file mode 100644 index 00000000..65a1f4ee --- /dev/null +++ b/lib/views/pages/sub_workorder/workorder_list.dart @@ -0,0 +1,103 @@ +import 'dart:developer'; + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/views/pages/sub_workorder/workorder_item.dart'; + +import '../../../controllers/localization/localization.dart'; +import '../../../controllers/providers/api/service_requests_provider.dart'; +import '../../../models/service_request/search_work_order.dart'; +import '../../../models/subtitle.dart'; +import '../../app_style/colors.dart'; +import '../../widgets/buttons/app_back_button.dart'; +import '../../widgets/loaders/lazy_loading.dart'; +import '../../widgets/loaders/no_item_found.dart'; +import 'create_sub_workorder_page.dart'; + +class WorkOrderList extends StatefulWidget { + List items; + final Future> Function() onLazyLoading; + + WorkOrderList({Key key, this.items, this.onLazyLoading}) : super(key: key); + + @override + State createState() => _WorkOrderListState(); +} + +class _WorkOrderListState extends State { + List _items; + + @override + void initState() { + super.initState(); + _items = widget.items; + } + + @override + Widget build(BuildContext context) { + final serviceRequestsProvider = Provider.of(context, listen: false); + Subtitle subtitle = AppLocalization.of(context).subtitle; + return Scaffold( + body: SafeArea( + child: Column( + children: [ + Container( + color: AColors.primaryColor, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), + child: Column( + children: [ + Row( + children: [ + const ABackButton(), + Expanded( + child: Center( + child: Text( + "Work Order List", + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), + ), + ), + ), + const SizedBox(width: 48), + ], + ), + ], + ), + ), + Expanded( + child: _items?.isEmpty ?? [] + ? NoItemFound( + message: subtitle.noServiceRequestFound, + ) + : LazyLoading( + nextPage: serviceRequestsProvider.nextPage, + onLazyLoad: () async { + _items = await widget.onLazyLoading(); + setState(() {}); + }, + child: ListView.builder( + itemCount: _items.length, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + itemBuilder: (context, itemIndex) { + return WorkOrderItem( + index: itemIndex, + onPressed: (model) { + // Navigator.of(context).push(MaterialPageRoute( + // builder: (_) => WorkOrderUpdate(item: model,))); + log(model?.toJson()?.toString()); + Navigator.push( + context, + MaterialPageRoute(builder: (context) => CreateSubWorkOrderPage(workOrder: model)), + ); + }, + item: _items[itemIndex], + ); + }, + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/views/pages/sub_workorder/workorder_update.dart b/lib/views/pages/sub_workorder/workorder_update.dart new file mode 100644 index 00000000..3970aeaa --- /dev/null +++ b/lib/views/pages/sub_workorder/workorder_update.dart @@ -0,0 +1,68 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/views/pages/sub_workorder/workorder_details.dart'; + +import '../../../controllers/localization/localization.dart'; +import '../../../models/service_request/search_work_order.dart'; +import '../../../models/subtitle.dart'; +import '../../app_style/colors.dart'; +import '../../widgets/buttons/app_back_button.dart'; +import '../../widgets/loaders/loading_manager.dart'; + +class WorkOrderUpdate extends StatefulWidget { + final SearchWorkOrder item; + + const WorkOrderUpdate({@required this.item, Key key}) : super(key: key); + + @override + State createState() => _WorkOrderUpdateState(); +} + +class _WorkOrderUpdateState extends State { + final GlobalKey _formKey = GlobalKey(); + Subtitle _subtitle; + bool _isLoading = false; + + @override + Widget build(BuildContext context) { + _subtitle = AppLocalization.of(context).subtitle; + + return Scaffold( + body: SafeArea( + child: Form( + key: _formKey, + child: LoadingManager( + isLoading: _isLoading, + isFailedLoading: false, + stateCode: 200, + onRefresh: () async {}, + child: Column( + children: [ + Container( + color: Theme.of(context).colorScheme.primary, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), + child: Row( + children: [ + const ABackButton(), + Expanded( + child: Center( + child: Text( + "Work Order", + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), + ), + ), + ), + const SizedBox(width: 58), + ], + ), + ), + WorkOrderDetails( + item: widget.item, + ) + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/views/pages/user/gas_refill/gas_refill_details.dart b/lib/views/pages/user/gas_refill/gas_refill_details.dart index d1d41eac..bc6f49a0 100644 --- a/lib/views/pages/user/gas_refill/gas_refill_details.dart +++ b/lib/views/pages/user/gas_refill/gas_refill_details.dart @@ -1,15 +1,16 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; +import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/http_status_manger/http_status_manger.dart'; +import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/gas_refill_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; -import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/gas_refill/gas_refill_model.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/app_style/sizing.dart'; +import 'package:test_sa/views/pages/user/gas_refill/request_gas_refill.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; import 'package:test_sa/views/widgets/buttons/app_icon_button.dart'; @@ -20,9 +21,12 @@ import 'package:test_sa/views/widgets/requests/request_status.dart'; import 'package:test_sa/views/widgets/status/gas_refill/gas_status.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; +import '../../../../models/enums/user_types.dart'; import '../../../app_style/colors.dart'; + class GasRefillDetails extends StatefulWidget { final GasRefillModel model; + const GasRefillDetails({Key key, this.model}) : super(key: key); @override @@ -30,7 +34,6 @@ class GasRefillDetails extends StatefulWidget { } class _GasRefillDetailsState extends State { - final GasRefillModel _model = GasRefillModel(); bool _enableEdit = false; bool _validate = false; @@ -41,41 +44,32 @@ class _GasRefillDetailsState extends State { Subtitle _subtitle; final GlobalKey _formKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); + _update() async { _validate = true; - if(!_formKey.currentState.validate()){ + if (!_formKey.currentState.validate()) { setState(() {}); return false; } _formKey.currentState.save(); - _isLoading =true; + _isLoading = true; setState(() {}); - int status = await _gasRefillProvider.updateModel( - user: _userProvider.user, - host: _settingProvider.host, - newModel: _model, - oldModel: widget.model - ); - _isLoading =false; + int status = await _gasRefillProvider.updateModel(user: _userProvider.user, host: _settingProvider.host, newModel: _model, oldModel: widget.model); + _isLoading = false; setState(() {}); - if(status >= 200 && status < 300){ + if (status >= 200 && status < 300) { Fluttertoast.showToast( msg: _subtitle.requestCompleteSuccessfully, ); _enableEdit = false; _validate = false; //Navigator.of(context).pop(); - }else{ - String errorMessage = HttpStatusManger.getStatusMessage( - status: status, subtitle: _subtitle); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - errorMessage - ), - ) - ); + } else { + String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(errorMessage), + )); } } @@ -105,40 +99,49 @@ class _GasRefillDetailsState extends State { children: [ Container( color: Theme.of(context).colorScheme.primary, - padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), child: Row( children: [ const ABackButton(), Expanded( child: Center( child: Text( - _subtitle.details, - style: Theme.of(context).textTheme.headline6.copyWith( - color: AColors.white, - fontStyle: FontStyle.italic - ), + "Gas Refill Request", + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), ), ), ), - if(_userProvider.user.type == UsersTypes.engineer) - AIconButton( - iconData: _enableEdit ? Icons.cancel : Icons.edit, - color: Theme.of(context).colorScheme.onPrimary, - buttonSize: 42, - backgroundColor: AColors.green, - onPressed: () async { - _enableEdit = !_enableEdit; - _model.fromGasRefillModel(widget.model); - setState(() {}); - }, - ), - const SizedBox(width: 16,) + if (_userProvider.user.type == UsersTypes.engineer) + AIconButton( + iconData: /*_enableEdit ? Icons.cancel :*/ Icons.edit, + color: Theme.of(context).colorScheme.onPrimary, + buttonSize: 42, + backgroundColor: AColors.green, + onPressed: () async { + // _enableEdit = !_enableEdit; + print(widget.model.startDate); + _model.fromGasRefillModel(widget.model); + print(widget.model.startDate); + // setState(() {}); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => RequestGasRefill( + gasRefillModel: widget.model, + ), + ), + ); + }, + ), + const SizedBox( + width: 16, + ) ], ), ), Expanded( child: SingleChildScrollView( - padding: EdgeInsets.all(16*AppStyle.getScaleFactor(context)), + padding: EdgeInsets.all(16 * AppStyle.getScaleFactor(context)), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -150,63 +153,89 @@ class _GasRefillDetailsState extends State { title: _subtitle.hospital, info: _model.clientName, ), - _enableEdit ? - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 8,), - ASubTitle(_subtitle.status), - if(_validate && _model.status == null) - ASubTitle(_subtitle.requiredWord,color: Colors.red,), - const SizedBox(height: 4,), - GasStatusMenu( - initialValue: _model.status, - onSelect: (status){ - _model.status = status; - }, - ) - ], - ): - Row( - children: [ - Expanded( - child: Text( - "${_subtitle.status} : ", - style: Theme.of(context).textTheme.subtitle2, - textScaleFactor: AppStyle.getScaleFactor(context), + RequestInfoRow( + title: "Building", + info: _model.building?.name, + ), + RequestInfoRow( + title: "Floor", + info: _model.floor?.name, + ), + RequestInfoRow( + title: _subtitle.startDate, + info: _model.startDate == null ? null : DateFormat.yMd().format(_model.startDate), + ), + RequestInfoRow( + title: _subtitle.endDate, + info: _model.endDate == null ? null : DateFormat.yMd().format(_model.endDate), + ), + _enableEdit + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox( + height: 8, + ), + ASubTitle(_subtitle.status), + if (_validate && _model.status == null) + ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), + GasStatusMenu( + initialValue: _model.status, + onSelect: (status) { + _model.status = status; + }, + ) + ], + ) + : Row( + children: [ + Expanded( + child: Text( + "${_subtitle.status} : ", + style: Theme.of(context).textTheme.subtitle2, + textScaleFactor: AppStyle.getScaleFactor(context), + ), + ), + if (_model.status?.id != null) StatusLabel(label: _model.status.name, color: AColors.getGasStatusColor(_model.status.id)), + ], ), - ), - StatusLabel(label: _model.status.label, - color: AColors.getGasStatusColor(_model.status.id) - ), - ], + const SizedBox( + height: 8, ), - const SizedBox(height: 8,), const ASubTitle("Gas Requests"), - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), ListView.builder( shrinkWrap: true, physics: const ClampingScrollPhysics(), itemCount: _model.details.length, - itemBuilder: (context,index){ + itemBuilder: (context, index) { final details = _model.details[index]; return GasRefillUpdateDetailsItem( details: details, validate: _validate, enableEdit: _enableEdit, ); - } - ), - if(_enableEdit) - Column( - children: [ - const SizedBox(height: 16,), - AButton( - text: _subtitle.update, - onPressed: _update, - ), - ], - ), + }), + if (_enableEdit) + Column( + children: [ + const SizedBox( + height: 16, + ), + AButton( + text: _subtitle.update, + onPressed: _update, + ), + ], + ), ], ), ), diff --git a/lib/views/pages/user/gas_refill/request_gas_refill.dart b/lib/views/pages/user/gas_refill/request_gas_refill.dart index 8e1f05ca..b638120a 100644 --- a/lib/views/pages/user/gas_refill/request_gas_refill.dart +++ b/lib/views/pages/user/gas_refill/request_gas_refill.dart @@ -1,28 +1,44 @@ +import 'dart:convert'; + import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/http_status_manger/http_status_manger.dart'; +import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/providers/api/gas_refill_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/controllers/validator/validator.dart'; import 'package:test_sa/models/gas_refill/gas_refill_details.dart'; import 'package:test_sa/models/gas_refill/gas_refill_model.dart'; +import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/subtitle.dart'; +import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; +import 'package:test_sa/views/widgets/date_and_time/time_picker.dart'; +import 'package:test_sa/views/widgets/gas_refill/building_type_menu.dart'; +import 'package:test_sa/views/widgets/gas_refill/department_type_menu.dart'; +import 'package:test_sa/views/widgets/gas_refill/floor_type_menu.dart'; import 'package:test_sa/views/widgets/gas_refill/gas_refill_create_details_item.dart'; +import 'package:test_sa/views/widgets/hospitals/hospital_auto_complete_field_new.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/gas_refill/gas_cylinder_size.dart'; +import 'package:test_sa/views/widgets/status/gas_refill/gas_cylinder_type.dart'; import 'package:test_sa/views/widgets/status/gas_refill/gas_status.dart'; import 'package:test_sa/views/widgets/status/gas_refill/gas_type.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; import '../../../../controllers/localization/localization.dart'; +import '../../../../controllers/providers/api/hospitals_provider.dart'; +import '../../../../models/enums/user_types.dart'; +import '../../../widgets/e_signature/e_signature.dart'; +import '../../../widgets/timer/app_timer.dart'; + class RequestGasRefill extends StatefulWidget { static const String id = "/request-gas-refill"; - const RequestGasRefill({Key key}) : super(key: key); + final GasRefillModel gasRefillModel; + const RequestGasRefill({this.gasRefillModel, Key key}) : super(key: key); @override State createState() => _RequestGasRefillState(); @@ -37,66 +53,85 @@ class _RequestGasRefillState extends State { GasRefillProvider _gasRefillProvider; GasRefillDetails _currentDetails = GasRefillDetails(); final TextEditingController _requestedQuantityController = TextEditingController(); - final GasRefillModel _formModel = GasRefillModel(details: []); + final TextEditingController _deliveredQuantityController = TextEditingController(); + GasRefillModel _formModel = GasRefillModel(details: []); final GlobalKey _formKey = GlobalKey(); final GlobalKey _DetailsKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); + bool _firstTime = true; + + @override + void initState() { + super.initState(); + if (widget.gasRefillModel != null) { + _formModel = widget.gasRefillModel; + } + } @override - void setState(VoidCallback fn){ - if(mounted) super.setState(() {}); + void setState(VoidCallback fn) { + if (mounted) super.setState(() {}); } _onSubmit() async { - if(_formModel.details.isEmpty){ - if(!_addNewModel()) return; + if (_formModel.details.isEmpty) { + if (!_addNewModel()) return; } - _isLoading =true; + _isLoading = true; setState(() {}); + if (widget.gasRefillModel != null) { + if (!_formModel.validate()) { + _isLoading = false; + setState(() {}); + return; + } + } - int status = await _gasRefillProvider.createModel( - user: _userProvider.user, - host: _settingProvider.host, - model: _formModel, - ); - _isLoading =false; + int status = widget.gasRefillModel == null + ? await _gasRefillProvider.createModel( + user: _userProvider.user, + host: _settingProvider.host, + model: _formModel, + ) + : await _gasRefillProvider.updateModel( + user: _userProvider.user, + host: _settingProvider.host, + oldModel: widget.gasRefillModel, + newModel: _formModel, + ); + _isLoading = false; setState(() {}); - if(status >= 200 && status < 300){ + if (status >= 200 && status < 300) { Fluttertoast.showToast( msg: _subtitle.requestCompleteSuccessfully, ); Navigator.of(context).pop(); - }else{ - String errorMessage = HttpStatusManger.getStatusMessage( - status: status, subtitle: _subtitle); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - errorMessage - ), - ) - ); + } else { + String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(errorMessage), + )); } } - bool _addNewModel(){ + bool _addNewModel() { _validate = true; - if(!_formKey.currentState.validate()){ + if (!_formKey.currentState.validate()) { setState(() {}); return false; } _formKey.currentState.save(); - if(!_currentDetails.validate()) { - setState(() { }); + if (!_currentDetails.validate()) { + setState(() {}); return false; } - - _formModel.details.insert(0,_currentDetails); + _formModel.details.insert(0, _currentDetails); _validate = false; Scrollable.ensureVisible(_DetailsKey.currentContext); _requestedQuantityController.clear(); + _deliveredQuantityController.clear(); _currentDetails = GasRefillDetails(); setState(() {}); return true; @@ -105,14 +140,36 @@ class _RequestGasRefillState extends State { @override void dispose() { _requestedQuantityController.dispose(); + _deliveredQuantityController.dispose(); super.dispose(); } + @override Widget build(BuildContext context) { _subtitle = AppLocalization.of(context).subtitle; _userProvider = Provider.of(context); _settingProvider = Provider.of(context); - _gasRefillProvider = Provider.of(context,listen: false); + if (_gasRefillProvider == null) { + _gasRefillProvider = Provider.of(context, listen: false); + _gasRefillProvider.reset(); + } + if (_firstTime) { + if (widget.gasRefillModel != null) { + _formModel.status = widget.gasRefillModel?.status ?? const Lookup(value: 0); + _gasRefillProvider.expectedDateTime = _formModel.expectedDate; + _gasRefillProvider.timer = TimerModel(startAt: widget.gasRefillModel?.startDate, endAt: widget.gasRefillModel?.endDate); + } else { + _gasRefillProvider.timer = null; + } + HospitalsProvider().getHospitalsListByVal(searchVal: _userProvider.user?.clientName).then((value) { + _gasRefillProvider.hospital = value?.firstWhere((element) => element.name == _userProvider.user?.clientName, orElse: () => null); + _gasRefillProvider.building = _gasRefillProvider.hospital?.buildings?.firstWhere((element) => element.name == widget.gasRefillModel?.building?.name, orElse: () => null); + _gasRefillProvider.floor = _gasRefillProvider.building?.floors?.firstWhere((element) => element.name == widget.gasRefillModel?.floor?.name, orElse: () => null); + _gasRefillProvider.department = _gasRefillProvider.floor?.departments?.firstWhere((element) => element.name == widget.gasRefillModel?.department?.departmentName, orElse: () => null); + _firstTime = false; + setState(() {}); + }); + } return Scaffold( key: _scaffoldKey, body: Form( @@ -132,12 +189,8 @@ class _RequestGasRefillState extends State { child: Padding( padding: const EdgeInsets.all(8.0), child: Text( - "Request Gas Refill", - style: Theme.of(context).textTheme.headline5.copyWith( - color: Theme.of(context).primaryColor, - fontSize: 28, - fontWeight: FontWeight.bold - ), + "${widget.gasRefillModel == null ? "Request" : "Update"} Gas Refill", + style: Theme.of(context).textTheme.headline5.copyWith(color: Theme.of(context).primaryColor, fontSize: 28, fontWeight: FontWeight.bold), ), ), ), @@ -155,89 +208,344 @@ class _RequestGasRefillState extends State { // _formModel.title = value; // }, // ), - // // const SizedBox(height: 8,), - // ASubTitle(_subtitle.status), - // if(_validate && _formModel.status == null) - // ASubTitle(_subtitle.requiredWord,color: Colors.red,), - // const SizedBox(height: 4,), - // GasStatusMenu( - // initialValue: _formModel.status, - // onSelect: (status){ - // _formModel.status = status; - // }, - // ), // const SizedBox(height: 8,), - // Divider(color: Theme.of(context).colorScheme.primary,), - const SizedBox(height: 4,), - const ASubTitle("Type"), - if(_validate && _currentDetails.type == null) - ASubTitle(_subtitle.requiredWord,color: Colors.red,), - const SizedBox(height: 4,), - GasTypeMenu( - initialValue: _currentDetails.type, - onSelect: (status){ - _currentDetails.type = status; + ASubTitle(_subtitle.status), + if (_validate && _formModel.status == null) + ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), + GasStatusMenu( + initialValue: _formModel.status ?? const Lookup(value: 0), + enabled: widget.gasRefillModel != null, + onSelect: (status) { + _formModel.status = status; }, ), - - // const SizedBox(height: 8,), - // const ASubTitle("Cylinder Size"), - // if(_validate && _currentDetails.cylinderSize == null) - // ASubTitle(_subtitle.requiredWord,color: Colors.red,), - // const SizedBox(height: 4,), - // GasCylinderSizeMenu( - // initialValue: _currentDetails.cylinderSize, - // onSelect: (status){ - // _currentDetails.cylinderSize = status; - // }, - // ), - const SizedBox(height: 8,), - ASubTitle(_subtitle.quantity), - if(_validate && _currentDetails.requestedQuantity == null) - ASubTitle(_subtitle.requiredWord,color: Colors.red,), - SizedBox(height: 4,), - ATextFormField( - initialValue: (_currentDetails?.requestedQuantity ?? "").toString(), - textAlign: TextAlign.center, - controller: _requestedQuantityController, - style: Theme.of(context).textTheme.subtitle1, - validator: (value) => - Validator.isNumeric(value) - ? null : "allow numbers only", - textInputType: TextInputType.number, - onSaved: (value){ - _currentDetails.requestedQuantity = int.tryParse(value); + const SizedBox( + height: 8, + ), + Divider( + color: Theme.of(context).colorScheme.primary, + ), + const SizedBox( + height: 4, + ), + HospitalAutoCompleteField( + enabled: false, + initialValue: _gasRefillProvider.hospital?.name, + // onSave: (value){ + // _search.hospital = value; + // }, + onSearch: (value) { + _gasRefillProvider.hospital = value; + _gasRefillProvider.building = null; + _gasRefillProvider.floor = null; + _gasRefillProvider.department = null; + setState(() {}); }, ), - const SizedBox(height: 16), - AButton( - text: _subtitle.add, - onPressed: _addNewModel, + const SizedBox( + height: 8, ), - if(_formModel.details.isNotEmpty) - const ASubTitle("Gas Requests"), - ListView.builder( - key: _DetailsKey, - shrinkWrap: true, - physics: const ClampingScrollPhysics(), - itemCount: _formModel.details.length, - itemBuilder: (context,index){ - final model = _formModel.details[index]; - return GasRefillCreateDetailsItem( - model: model, - onDelete: (){ - _formModel.details.remove(model); - setState(() {}); - }, - ); - } + BuildingTypeMenu( + initialValue: _gasRefillProvider?.building, + building: _gasRefillProvider?.hospital?.buildings, + enabled: widget.gasRefillModel == null, + onSelect: (status) { + _gasRefillProvider.building = status; + setState(() {}); + }, + ), + const SizedBox(height: 8), + FloorTypeMenu( + initialValue: _gasRefillProvider?.floor, + floors: _gasRefillProvider?.building?.floors, + enabled: widget.gasRefillModel == null, + onSelect: (status) { + _gasRefillProvider.floor = status; + setState(() {}); + }, + ), + const SizedBox(height: 8), + DepartmentTypeMenu( + initialValue: _gasRefillProvider?.department, + departments: _gasRefillProvider?.floor?.departments, + enabled: widget.gasRefillModel == null, + onSelect: (status) { + _gasRefillProvider.department = status; + setState(() {}); + }, ), + const SizedBox(height: 8), + if (widget.gasRefillModel != null) ASubTitle(_subtitle.workingHours), + if (widget.gasRefillModel != null) const SizedBox(height: 8), + if (widget.gasRefillModel != null) + Row( + children: [ + Expanded( + child: AppTimer( + timer: _gasRefillProvider.timer, + onChange: (timer) async { + _gasRefillProvider.timer = timer; + _formModel.workingHours = num.tryParse((((timer?.durationInSecond ?? 0) / 60) / 60)?.toStringAsFixed(2) ?? "0"); + return true; + }, + ), + ), + ], + ), + const SizedBox(height: 8), + if (_userProvider.user?.type == UsersTypes.normal_user || widget.gasRefillModel != null) + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const ASubTitle("Expected Date"), + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), + ), + ADateTimePicker( + date: _gasRefillProvider.expectedDateTime, + from: DateTime.now().subtract(const Duration(days: 365)), + to: DateTime.now().add(const Duration(days: 365)), + onDateTimePicker: (date) { + _gasRefillProvider.expectedDateTime = date; + _formModel.expectedDate = _gasRefillProvider.expectedDateTime; + setState(() {}); + }, + ), + ], + ), + // if (_userProvider.user?.type == UsersTypes.engineer) + // Column( + // children: [ + // Row( + // children: [ + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.stretch, + // children: [ + // const ASubTitle("Start of Work"), + // SizedBox( + // height: 8 * AppStyle.getScaleFactor(context), + // ), + // ADateTimePicker( + // date: _gasRefillProvider.startDate, + // from: DateTime.now().subtract(const Duration(days: 365)), + // to: DateTime.now().add(const Duration(days: 365)), + // onDateTimePicker: (date) { + // _gasRefillProvider.startDate = date; + // setState(() {}); + // }, + // ), + // ], + // ), + // ), + // const SizedBox(width: 8), + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.stretch, + // children: [ + // const ASubTitle("End of Work"), + // SizedBox( + // height: 8 * AppStyle.getScaleFactor(context), + // ), + // ADateTimePicker( + // date: _gasRefillProvider.endDate, + // from: DateTime.now().subtract(const Duration(days: 365)), + // to: DateTime.now().add(const Duration(days: 365)), + // onDateTimePicker: (date) { + // _gasRefillProvider.endDate = date; + // setState(() {}); + // }, + // ), + // ], + // ), + // ), + // ], + // ), + // const SizedBox(height: 8), + // ASubTitle(_subtitle.workingHours), + // const SizedBox(height: 4), + // ATextFormField( + // initialValue: null, + // textAlign: TextAlign.center, + // hintText: _gasRefillProvider.startDate == null + // ? "0" + // : ((_gasRefillProvider.endDate?.difference(_gasRefillProvider.startDate)?.inMinutes ?? 0) / 60)?.toStringAsFixed(2)?.toString() ?? "0", + // enable: false, + // style: Theme.of(context).textTheme.subtitle1, + // validator: (value) => Validator.isNumeric(value) ? null : _subtitle.requiredWord, + // textInputType: TextInputType.number, + // onSaved: (value) { + // // _serviceReport.workHours = value; + // }, + // ), + // ], + // ), + if (widget.gasRefillModel == null) + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 8), + Divider(color: Theme.of(context).colorScheme.primary), + const SizedBox(height: 4), + const ASubTitle("Gas Type"), + if (_validate && _currentDetails.type == null) ASubTitle(_subtitle.requiredWord, color: Colors.red), + const SizedBox(height: 4), + GasTypeMenu( + initialValue: _currentDetails.type, + onSelect: (status) { + _currentDetails.type = status; + }, + ), + const SizedBox(height: 8), + const ASubTitle("Cylinder Size"), + if (_validate && _currentDetails.cylinderSize == null) + ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), + GasCylinderSizeMenu( + initialValue: _currentDetails.cylinderSize, + onSelect: (status) { + _currentDetails.cylinderSize = status; + }, + ), + const SizedBox( + height: 8, + ), + const ASubTitle("Cylinder Type"), + if (_validate && _currentDetails.cylinderSize == null) + ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), + GasCylinderTypesMenu( + initialValue: _currentDetails.cylinderType, + onSelect: (status) { + _currentDetails.cylinderType = status; + }, + ), + const SizedBox( + height: 8, + ), + ASubTitle(_subtitle.requestedQuantity), + if (_validate && _currentDetails?.requestedQuantity == null) + ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ), + SizedBox( + height: 4, + ), + ATextFormField( + initialValue: (_currentDetails?.requestedQuantity ?? "").toString(), + textAlign: TextAlign.center, + controller: _requestedQuantityController, + style: Theme.of(context).textTheme.subtitle1, + validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only", + textInputType: TextInputType.number, + onChange: (value) { + _currentDetails?.requestedQuantity = double.tryParse(value); + }, + ), + if (widget.gasRefillModel != null) const SizedBox(height: 16), + if (widget.gasRefillModel != null) ASubTitle(_subtitle.deliveredQuantity), + if (widget.gasRefillModel != null && _validate && _currentDetails?.deliveredQuantity == null) + ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ), + if (widget.gasRefillModel != null) const SizedBox(height: 4), + if (widget.gasRefillModel != null) + ATextFormField( + initialValue: (_currentDetails?.deliveredQuantity ?? "").toString(), + textAlign: TextAlign.center, + controller: _deliveredQuantityController, + style: Theme.of(context).textTheme.subtitle1, + validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only", + textInputType: TextInputType.number, + onChange: (value) { + _currentDetails?.deliveredQuantity = double.tryParse(value); + }, + ), + const SizedBox(height: 16), + AButton( + text: _subtitle.add, + onPressed: _addNewModel, + ), + ], + ), + const SizedBox(height: 16), + if (_formModel.details.isNotEmpty) const ASubTitle("Gas Requests"), + ListView.builder( + key: _DetailsKey, + shrinkWrap: true, + physics: const ClampingScrollPhysics(), + itemCount: _formModel.details.length, + itemBuilder: (context, index) { + final model = _formModel.details[index]; + return GasRefillCreateDetailsItem( + isUpdate: widget.gasRefillModel != null, + model: model, + onPressed: () { + if (widget.gasRefillModel != null) { + model.selectedForEditing = !(model.selectedForEditing ?? false); + } + if (widget.gasRefillModel == null) { + _formModel.details.remove(model); + } + setState(() {}); + }, + ); + }), + if (widget.gasRefillModel != null) const SizedBox(height: 16), + if (widget.gasRefillModel != null) const ASubTitle("Nurse Signature"), + if (widget.gasRefillModel != null) + ESignature( + oldSignature: _formModel.signatureNurse, + newSignature: _formModel.localNurseSignature, + onChange: (signature) { + if (signature == null || signature.isEmpty) { + return; + } + _formModel.localNurseSignature = signature; + _formModel.signatureNurse = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + }, + ), + if (widget.gasRefillModel != null) + const SizedBox( + height: 8, + ), + if (widget.gasRefillModel != null) const ASubTitle("Engineer Signature"), + if (widget.gasRefillModel != null) + ESignature( + oldSignature: _formModel.signatureEngineer, + newSignature: _formModel.localNurseSignature, + onChange: (signature) { + if (signature == null || signature.isEmpty) { + return; + } + _formModel.localNurseSignature = signature; + _formModel.signatureEngineer = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + }, + ), const SizedBox(height: 16), AButton( - text: _subtitle.submit, + text: widget.gasRefillModel == null ? _subtitle.submit : _subtitle.update, onPressed: _onSubmit, ), - const SizedBox(height: 100,) + const SizedBox(height: 100) ], ), ), @@ -247,4 +555,3 @@ class _RequestGasRefillState extends State { ); } } - diff --git a/lib/views/pages/user/gas_refill/track_gas_refill.dart b/lib/views/pages/user/gas_refill/track_gas_refill.dart index 713c9530..7a1d728b 100644 --- a/lib/views/pages/user/gas_refill/track_gas_refill.dart +++ b/lib/views/pages/user/gas_refill/track_gas_refill.dart @@ -9,6 +9,9 @@ import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/gas_refill/gas_refill_list.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; + +import '../../../widgets/switch_button.dart'; + class TrackGasRefillPage extends StatefulWidget { static const String id = "/track-gas-refill"; @@ -18,14 +21,19 @@ class TrackGasRefillPage extends StatefulWidget { State createState() => _TrackGasRefillPageState(); } -class _TrackGasRefillPageState extends State - with TickerProviderStateMixin{ +class _TrackGasRefillPageState extends State with TickerProviderStateMixin { GasRefillProvider _gasRefillProvider; UserProvider _userProvider; SettingProvider _settingProvider; + bool mostRecent = false; + @override Widget build(BuildContext context) { - _gasRefillProvider = Provider.of(context); + if (_gasRefillProvider == null) { + _gasRefillProvider = Provider.of(context); + //_gasRefillProvider?.isLoading = false; + _gasRefillProvider.reset(); + } _userProvider = Provider.of(context); _settingProvider = Provider.of(context); Subtitle _subtitle = AppLocalization.of(context).subtitle; @@ -48,31 +56,44 @@ class _TrackGasRefillPageState extends State Column( children: [ Container( - color:AColors.white, - padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), + color: AColors.white, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), child: Column( children: [ Row( children: [ - ABackButton(), + const ABackButton(), Expanded( child: Center( child: Text( - _subtitle.serviceRequests, - style: Theme.of(context).textTheme.headline6.copyWith( - color: AColors.grey3A, - fontStyle: FontStyle.italic - ), + "Gas Refill Requests", + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.grey3A, fontStyle: FontStyle.italic), ), ), ), - const SizedBox(width: 48,) + const SizedBox( + width: 48, + ) ], ), - ], ), ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: ASwitchButton( + title: "Most Recent", + value: mostRecent, + onChange: (value) async { + mostRecent = value; + await _gasRefillProvider.getRequests( + user: _userProvider.user, + host: _settingProvider.host, + mostRecent: mostRecent, + ); + }, + ), + ), Expanded( child: GasRefillList( nextPage: _gasRefillProvider.nextPage, @@ -87,7 +108,6 @@ class _TrackGasRefillPageState extends State ), ], ), - ], ), ), diff --git a/lib/views/pages/user/land_page.dart b/lib/views/pages/user/land_page.dart index dd37a8af..e249206d 100644 --- a/lib/views/pages/user/land_page.dart +++ b/lib/views/pages/user/land_page.dart @@ -1,6 +1,5 @@ import 'dart:io'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; @@ -24,9 +23,9 @@ import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/pages/device_transfer/request_device_transfer.dart'; import 'package:test_sa/views/pages/device_transfer/track_device_transfer.dart'; +import 'package:test_sa/views/pages/sub_workorder/search_sub_workorder_page.dart'; import 'package:test_sa/views/pages/user/gas_refill/request_gas_refill.dart'; import 'package:test_sa/views/pages/user/gas_refill/track_gas_refill.dart'; -import 'package:test_sa/views/pages/user/notifications/notifications_page.dart'; import 'package:test_sa/views/pages/user/requests/create_request.dart'; import 'package:test_sa/views/pages/user/visits/regular_visits_page.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; @@ -153,7 +152,7 @@ class _LandPageState extends State { mainAxisSpacing: 12, childAspectRatio: 1, children: [ - if (_userProvider.user.type == UsersTypes.normal_user) + if (_userProvider.user != null && _userProvider.user.type == UsersTypes.normal_user) LandPageItem( text: _subtitle.newServiceRequest, icon: FontAwesomeIcons.tools, @@ -184,7 +183,7 @@ class _LandPageState extends State { // Navigator.of(context).pushNamed(PreventiveMaintenanceVisitsPage.id); // }, // ), - if (_userProvider.user.type != UsersTypes.engineer) + if (_userProvider?.user != null && _userProvider?.user?.type != UsersTypes.engineer) LandPageItem( text: "Request Gas Refill", icon: FontAwesomeIcons.truckFast, @@ -200,19 +199,27 @@ class _LandPageState extends State { }, ), LandPageItem( - text: "transfer Device", + text: "Transfer Asset", icon: FontAwesomeIcons.rightLeft, onPressed: () { Navigator.of(context).pushNamed(RequestDeviceTransfer.id); }, ), LandPageItem( - text: "Track Device Transfer", + text: "Track Asset Transfer", icon: FontAwesomeIcons.peopleCarryBox, onPressed: () { Navigator.of(context).pushNamed(TrackDeviceTransferPage.id); }, ), + if (_userProvider?.user != null && _userProvider?.user?.type != UsersTypes.normal_user) + LandPageItem( + text: "Create Sub Work Order", + svgPath: "assets/images/sub_workorder_icon.svg", + onPressed: () { + Navigator.of(context).pushNamed(SearchSubWorkOrderPage.id); + }, + ), ], ), ], @@ -235,6 +242,7 @@ class _LandPageState extends State { _regularVisitsProvider.reset(); _preventiveMaintenanceVisitsProvider.reset(); _settingProvider.resetSettings(); + _userProvider.reset(); Navigator.of(context).pop(); } }, @@ -278,13 +286,17 @@ class _LandPageState extends State { decoration: BoxDecoration(border: Border.all(color: Theme.of(context).primaryColor, width: 2), shape: BoxShape.circle), child: ClipOval( child: ClipOval( - child: Icon(Icons.person,size: 36,color: Theme.of(context).colorScheme.primary,), + child: Icon( + Icons.person, + size: 36, + color: Theme.of(context).colorScheme.primary, + ), ), ), ), 12.width, Text( - _userProvider.user.userName, + _userProvider.user?.userName ?? "??", style: Theme.of(context).textTheme.headline6.copyWith( fontWeight: FontWeight.w600, ), @@ -329,13 +341,13 @@ class _LandPageState extends State { ), ], ), - DrawerItem( - icon: Icons.notifications, - title: _subtitle.notifications, - onPressed: () { - Navigator.of(context).pushNamed(NotificationsPage.id); - }, - ), + // DrawerItem( + // icon: Icons.notifications, + // title: _subtitle.notifications, + // onPressed: () { + // Navigator.of(context).pushNamed(NotificationsPage.id); + // }, + // ), DrawerItem( icon: Icons.mail, title: _subtitle.email, @@ -380,12 +392,12 @@ class _LandPageState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Text( - "Powered By NewTrack", + "Powered By Cloud Solutions", style: Theme.of(context).textTheme.headline6.copyWith(fontWeight: FontWeight.w500, color: AColors.grey3A, fontSize: 12), textScaleFactor: AppStyle.getScaleFactor(context), ), 6.width, - Image.asset("assets/images/qr.jpeg", width: 32, height: 32, color: AColors.grey3A) + Image.asset("assets/images/cloud_logo.png", width: 32, height: 32) ], ).paddingOnly(left: 20, right: 20, top: 8, bottom: 8), ], diff --git a/lib/views/pages/user/notifications/notifications_list.dart b/lib/views/pages/user/notifications/notifications_list.dart index 2df3171d..61c7c331 100644 --- a/lib/views/pages/user/notifications/notifications_list.dart +++ b/lib/views/pages/user/notifications/notifications_list.dart @@ -1,3 +1,4 @@ +import 'package:flutter/material.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/models/app_notification.dart'; import 'package:test_sa/models/subtitle.dart'; @@ -5,7 +6,7 @@ import 'package:test_sa/views/pages/user/requests/future_request_service_details import 'package:test_sa/views/widgets/loaders/lazy_loading.dart'; import 'package:test_sa/views/widgets/loaders/no_item_found.dart'; import 'package:test_sa/views/widgets/notifications/notification_item.dart'; -import 'package:flutter/material.dart'; + class NotificationsList extends StatelessWidget { final List notifications; final bool nextPage; @@ -16,28 +17,26 @@ class NotificationsList extends StatelessWidget { @override Widget build(BuildContext context) { Subtitle _subtitle = AppLocalization.of(context).subtitle; - if(notifications.length == 0){ - return NoItemFound(message: _subtitle.notificationsNotFound,); + if (notifications.length == 0) { + return NoItemFound( + message: _subtitle.notificationsNotFound, + ); } return LazyLoading( nextPage: nextPage, onLazyLoad: onLazyLoad, child: ListView.builder( - physics: BouncingScrollPhysics(), - itemCount: notifications.length, - padding: EdgeInsets.symmetric(horizontal: 16,vertical: 8), - itemBuilder: (context,itemIndex){ + physics: BouncingScrollPhysics(), + itemCount: notifications.length, + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), + itemBuilder: (context, itemIndex) { return NotificationItem( notification: notifications[itemIndex], - onPressed: (notification){ - Navigator.of(context).pushNamed( - FutureRequestServiceDetails.id, - arguments: notification.requestId - ); + onPressed: (notification) { + Navigator.of(context).pushNamed(FutureRequestServiceDetails.id, arguments: notification.requestId); }, ); - } - ), + }), ); } } diff --git a/lib/views/pages/user/notifications/notifications_page.dart b/lib/views/pages/user/notifications/notifications_page.dart index a0e85259..614855d4 100644 --- a/lib/views/pages/user/notifications/notifications_page.dart +++ b/lib/views/pages/user/notifications/notifications_page.dart @@ -9,18 +9,20 @@ import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/pages/user/notifications/notifications_list.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; + class NotificationsPage extends StatefulWidget { static final String id = "/notifications"; + @override _NotificationsPageState createState() => _NotificationsPageState(); } -class _NotificationsPageState extends State - with TickerProviderStateMixin{ +class _NotificationsPageState extends State with TickerProviderStateMixin { NotificationsProvider _notificationsProvider; UserProvider _userProvider; SettingProvider _settingProvider; Subtitle _subtitle; + @override Widget build(BuildContext context) { _notificationsProvider = Provider.of(context); @@ -36,9 +38,9 @@ class _NotificationsPageState extends State onRefresh: () async { _notificationsProvider.reset(); await _notificationsProvider.getNotifications( - user: _userProvider.user, - host: _settingProvider.host, - hospitalId: _userProvider.user.hospital.id, + user: _userProvider.user, + host: _settingProvider.host, + hospitalId: _userProvider.user.clientId, ); }, child: Stack( @@ -46,8 +48,8 @@ class _NotificationsPageState extends State Column( children: [ Container( - color:AColors.primaryColor, - padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), + color: AColors.primaryColor, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), child: Column( children: [ Row( @@ -57,17 +59,15 @@ class _NotificationsPageState extends State child: Center( child: Text( _subtitle.notifications, - style: Theme.of(context).textTheme.headline6.copyWith( - color: AColors.white, - fontStyle: FontStyle.italic - ), + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), ), ), ), - SizedBox(width: 48,) + SizedBox( + width: 48, + ) ], ), - ], ), ), @@ -78,7 +78,7 @@ class _NotificationsPageState extends State await _notificationsProvider.getNotifications( user: _userProvider.user, host: _settingProvider.host, - hospitalId: _userProvider.user.hospital.id, + hospitalId: _userProvider.user.clientId, ); }, notifications: _notificationsProvider.notifications, @@ -86,7 +86,6 @@ class _NotificationsPageState extends State ), ], ), - ], ), ), diff --git a/lib/views/pages/user/profile_page.dart b/lib/views/pages/user/profile_page.dart index 514655e9..a5b88dae 100644 --- a/lib/views/pages/user/profile_page.dart +++ b/lib/views/pages/user/profile_page.dart @@ -1,8 +1,10 @@ -import 'package:test_sa/controllers/http_status_manger/http_status_manger.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/controllers/validator/validator.dart'; +import 'package:test_sa/models/hospital.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/models/user.dart'; import 'package:test_sa/views/app_style/colors.dart'; @@ -10,14 +12,12 @@ import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; -import 'package:test_sa/views/widgets/departments/department_button.dart'; import 'package:test_sa/views/widgets/hospitals/hospital_button.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; -import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; + class ProfilePage extends StatefulWidget { static final String id = "/user/profile"; + @override _ProfilePageState createState() => _ProfilePageState(); } @@ -31,6 +31,7 @@ class _ProfilePageState extends State { bool _firstTime = true; final GlobalKey _formKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); + @override Widget build(BuildContext context) { _userProvider = Provider.of(context); @@ -38,13 +39,13 @@ class _ProfilePageState extends State { _width = MediaQuery.of(context).size.width; _height = MediaQuery.of(context).size.height; Subtitle _subtitle = AppLocalization.of(context).subtitle; - if(_firstTime){ + if (_firstTime) { _user = User.fromJson(_userProvider.user.toJson()); _firstTime = false; } return Scaffold( key: _scaffoldKey, - body:LoadingManager( + body: LoadingManager( isLoading: _userProvider.isLoading, isFailedLoading: false, stateCode: 200, @@ -60,23 +61,19 @@ class _ProfilePageState extends State { Hero( tag: "logo", child: Image( - height: _height/4, + height: _height / 4, image: AssetImage("assets/images/logo.png"), ), ), Container( - padding: EdgeInsets.symmetric(horizontal: 16,vertical: 16), + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16), margin: EdgeInsets.symmetric(horizontal: 16), - decoration: BoxDecoration( - color: AColors.primaryColor, - borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), - boxShadow: [ - BoxShadow( - color: AColors.grey, - offset: Offset(0,-1), - ) - ] - ), + decoration: BoxDecoration(color: AColors.primaryColor, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [ + BoxShadow( + color: AColors.grey, + offset: Offset(0, -1), + ) + ]), child: Column( children: [ ATextFormField( @@ -85,13 +82,14 @@ class _ProfilePageState extends State { enable: false, prefixIconData: Icons.account_circle, style: Theme.of(context).textTheme.headline6, - validator: (value) => Validator.hasValue(value) - ? null : _subtitle.nameValidateMessage, - onSaved: (value){ + validator: (value) => Validator.hasValue(value) ? null : _subtitle.nameValidateMessage, + onSaved: (value) { _user.userName = value; }, ), - SizedBox(height: 8,), + SizedBox( + height: 8, + ), ATextFormField( initialValue: _user.email, hintText: _subtitle.email, @@ -99,110 +97,108 @@ class _ProfilePageState extends State { prefixIconData: Icons.email, textInputType: TextInputType.emailAddress, style: Theme.of(context).textTheme.headline6, - validator: (value) => Validator.isEmail(value) - ? null : _subtitle.emailValidateMessage, - onSaved: (value){ + validator: (value) => Validator.isEmail(value) ? null : _subtitle.emailValidateMessage, + onSaved: (value) { _user.email = value; }, ), - SizedBox(height: 8,), + SizedBox( + height: 8, + ), AbsorbPointer( child: HospitalButton( - hospital: _user.hospital, - onHospitalPick: (hospital){ - _user.hospital = hospital; + hospital: Hospital(name: _user.clientName, id: _user.clientId), + onHospitalPick: (hospital) { + _user.clientName = hospital.name; + _user.clientId = hospital.id; setState(() {}); }, ), ), - SizedBox(height: 8,), - DepartmentButton( - department: _user.department, - onDepartmentPick: (department){ - _user.department = department; - setState(() {}); - }, + SizedBox( + height: 8, + ), + // DepartmentButton( + // department: Department(name: _user.departmentName, id: _user.departmentId), + // onDepartmentPick: (department) { + // _user.departmentName = department.name; + // _user.departmentId = department.id; + // setState(() {}); + // }, + // ), + SizedBox( + height: 8, ), - SizedBox(height: 8,), ATextFormField( initialValue: _user.phoneNumber, hintText: _subtitle.phoneNumber, style: Theme.of(context).textTheme.headline6, prefixIconData: Icons.phone_android, - validator: (value) => - Validator.isPhoneNumber(value) ? null : _subtitle.phoneNumberValidateMessage, + validator: (value) => Validator.isPhoneNumber(value) ? null : _subtitle.phoneNumberValidateMessage, textInputType: TextInputType.phone, - onSaved: (value){ + onSaved: (value) { _user.phoneNumber = value; }, ), - SizedBox(height: 8,), - ATextFormField( - initialValue: _user.whatsApp, - hintText: _subtitle.whatsApp, - style: Theme.of(context).textTheme.headline6, - prefixIconData: FontAwesomeIcons.whatsapp, - prefixIconSize: 36, - validator: (value) => - Validator.isPhoneNumber(value) ? null : _subtitle.phoneNumberValidateMessage, - textInputType: TextInputType.phone, - onSaved: (value){ - _user.whatsApp = value; - }, + SizedBox( + height: 8, ), + // ATextFormField( + // initialValue: _user.whatsApp, + // hintText: _subtitle.whatsApp, + // style: Theme.of(context).textTheme.headline6, + // prefixIconData: FontAwesomeIcons.whatsapp, + // prefixIconSize: 36, + // validator: (value) => + // Validator.isPhoneNumber(value) ? null : _subtitle.phoneNumberValidateMessage, + // textInputType: TextInputType.phone, + // onSaved: (value){ + // _user.whatsApp = value; + // }, + // ), ], ), ), - SizedBox(height: 16,), + SizedBox( + height: 16, + ), Center( child: SizedBox( height: _width / 8, - width: _width/1.2, + width: _width / 1.2, child: AButton( text: _subtitle.update, onPressed: () async { - if(!_formKey.currentState.validate()) - return; - _formKey.currentState.save(); - if(_user.department?.id == null){ - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - _subtitle.unitRequired - ), - ) - ); - return; - } - int status = await _userProvider.updateProfile( - user: _user, - host: _settingProvider.host, - ); - if(status >= 200 && status < 300){ - _settingProvider.setUser(_userProvider.user); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - _subtitle.requestCompleteSuccessfully - ), - ) - ); - }else{ - String errorMessage = HttpStatusManger.getStatusMessage( - status: status, subtitle: _subtitle); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - errorMessage - ), - ) - ); - } + // if (!_formKey.currentState.validate()) return; + // _formKey.currentState.save(); + // if (_user.departmentId == null) { + // ScaffoldMessenger.of(context).showSnackBar(SnackBar( + // content: Text(_subtitle.unitRequired), + // )); + // return; + // } + // int status = await _userProvider.updateProfile( + // user: _user, + // host: _settingProvider.host, + // ); + // if (status >= 200 && status < 300) { + // _settingProvider.setUser(_userProvider.user); + // ScaffoldMessenger.of(context).showSnackBar(SnackBar( + // content: Text(_subtitle.requestCompleteSuccessfully), + // )); + // } else { + // String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle); + // ScaffoldMessenger.of(context).showSnackBar(SnackBar( + // content: Text(errorMessage), + // )); + // } }, ), ), ), - SizedBox(height: 32,), + SizedBox( + height: 32, + ), ], ), ), diff --git a/lib/views/pages/user/report_issues_page.dart b/lib/views/pages/user/report_issues_page.dart index a1641b24..0da3b23c 100644 --- a/lib/views/pages/user/report_issues_page.dart +++ b/lib/views/pages/user/report_issues_page.dart @@ -16,11 +16,13 @@ import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; import 'package:test_sa/views/widgets/issues/report_issue_item.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; + class ReportIssuesPage extends StatefulWidget { static final String id = "/report-issue"; final ServiceRequest serviceRequest; const ReportIssuesPage({Key key, this.serviceRequest}) : super(key: key); + @override _ReportIssuesPageState createState() => _ReportIssuesPageState(); } @@ -34,6 +36,7 @@ class _ReportIssuesPageState extends State { UserProvider _userProvider; SettingProvider _settingProvider; final GlobalKey _formKey = GlobalKey(); + @override Widget build(BuildContext context) { Subtitle _subtitle = AppLocalization.of(context).subtitle; @@ -64,22 +67,18 @@ class _ReportIssuesPageState extends State { ), child: Text( _subtitle.reportIssue, - style: Theme.of(context).textTheme.headline5.copyWith( - color: AColors.cyan, - fontWeight: FontWeight.bold - ), + style: Theme.of(context).textTheme.headline5.copyWith(color: AColors.cyan, fontWeight: FontWeight.bold), ), ), ), Image( - height: _height/8, + height: _height / 8, image: AssetImage("assets/images/logo.png"), ), - Container( padding: EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, + horizontal: 16, + vertical: 16, ), decoration: BoxDecoration( color: AColors.grey, @@ -90,10 +89,9 @@ class _ReportIssuesPageState extends State { boxShadow: [ BoxShadow( color: AColors.grey, - offset: Offset(0,-1), + offset: Offset(0, -1), ) - ] - ), + ]), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -102,32 +100,30 @@ class _ReportIssuesPageState extends State { hintText: _subtitle.title, textAlign: TextAlign.center, style: Theme.of(context).textTheme.headline6, - validator: (value) => - Validator.hasValue(value) - ? null : _subtitle.titleValidateMessage, + validator: (value) => Validator.hasValue(value) ? null : _subtitle.titleValidateMessage, textInputType: TextInputType.name, - onSaved: (value){ + onSaved: (value) { _issue.title = value; }, ), - SizedBox(height: 8,), - Column( - children: List.generate( - _issues.length, - (index) => ReportIssueItem( - isSelected: _issue.reports.contains(index), - issueInfo: _issues[index], - onChange: (info,value){ - if(value){ - _issue.reports.add(index); - } else { - _issue.reports.remove(index); - } - setState(() {}); - }, - ) - ) + SizedBox( + height: 8, ), + Column( + children: List.generate( + _issues.length, + (index) => ReportIssueItem( + isSelected: _issue.reports.contains(index), + issueInfo: _issues[index], + onChange: (info, value) { + if (value) { + _issue.reports.add(index); + } else { + _issue.reports.remove(index); + } + setState(() {}); + }, + ))), Padding( padding: const EdgeInsets.all(8.0), child: Text( @@ -139,7 +135,7 @@ class _ReportIssuesPageState extends State { hintText: _subtitle.description, style: Theme.of(context).textTheme.subtitle1, textInputType: TextInputType.multiline, - onSaved: (value){ + onSaved: (value) { _issue.description = value; }, ), @@ -148,20 +144,19 @@ class _ReportIssuesPageState extends State { child: AButton( text: _subtitle.submit, onPressed: () async { - if(!_formKey.currentState.validate()) - return; + if (!_formKey.currentState.validate()) return; _formKey.currentState.save(); _issue.serviceRequestId = widget.serviceRequest.id; - _isLoading =true; + _isLoading = true; setState(() {}); int status = await _serviceRequestsProvider.createIssueReport( user: _userProvider.user, host: _settingProvider.host, issue: _issue, ); - _isLoading =false; + _isLoading = false; setState(() {}); - if(status >= 200 && status < 300){ + if (status >= 200 && status < 300) { Fluttertoast.showToast( msg: _subtitle.requestCompleteSuccessfully, ); diff --git a/lib/views/pages/user/requests/create_request.dart b/lib/views/pages/user/requests/create_request.dart index 86b819e8..9201149b 100644 --- a/lib/views/pages/user/requests/create_request.dart +++ b/lib/views/pages/user/requests/create_request.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/http_status_manger/http_status_manger.dart'; +import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; @@ -27,38 +27,62 @@ import 'package:test_sa/views/widgets/sound/record_sound.dart'; import 'package:test_sa/views/widgets/speech_to_text/speech_to_text.dart'; import 'package:test_sa/views/widgets/status/service_request/service_request_defect_types_mune.dart'; import 'package:test_sa/views/widgets/status/service_request/service_request_priority_mune.dart'; +import 'package:test_sa/views/widgets/status/service_request/service_request_through_mune.dart'; +import 'package:test_sa/views/widgets/status/service_request/service_request_types_mune.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; +import '../../../../controllers/providers/api/status_drop_down/service_reqest/service_request_through_provider.dart'; +import '../../../../controllers/providers/api/status_drop_down/service_reqest/service_request_type_provider.dart'; +import '../../../app_style/sizing.dart'; +import '../../../widgets/date_and_time/date_picker.dart'; +import '../../../widgets/status/service_request/service_request_first_action.dart'; +import '../../../widgets/status/service_request/service_request_loan_availability.dart'; + class CreateRequestPage extends StatefulWidget { - static final String id = "/create-request"; + static const String id = "/create-request"; + final ServiceRequest serviceRequest; + + const CreateRequestPage({this.serviceRequest, Key key}) : super(key: key); @override - _CreateRequestPageState createState() => _CreateRequestPageState(); + CreateRequestPageState createState() => CreateRequestPageState(); } -class _CreateRequestPageState extends State { +class CreateRequestPageState extends State { double _height; UserProvider _userProvider; SettingProvider _settingProvider; ServiceRequestsProvider _serviceRequestsProvider; - ServiceRequest _serviceRequest = ServiceRequest(); - List _deviceImages = []; + ServiceRequest _serviceRequest; + final List _deviceImages = []; bool _isLoading = false; + bool _showDatePicker = false; Device _device; Subtitle _subtitle; final GlobalKey _formKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); - TextEditingController _controller; + TextEditingController _maintenanceController, _commentController, _reviewCommentController; + DateTime _dateTime; @override void initState() { - _controller = TextEditingController(); + _maintenanceController = TextEditingController(); + _commentController = TextEditingController(); + if (widget.serviceRequest != null) { + _serviceRequest = widget.serviceRequest; + _device = _serviceRequest.device; + _deviceImages.addAll(_serviceRequest.devicePhotos.map((e) => File(e)).toList()); + _showDatePicker = _serviceRequest.firstAction != null && _serviceRequest.firstAction.name == "Need a visit"; + } else { + _serviceRequest = ServiceRequest(); + } super.initState(); } @override void dispose() { - _controller.dispose(); + _maintenanceController.dispose(); + _commentController.dispose(); super.dispose(); } @@ -84,21 +108,19 @@ class _CreateRequestPageState extends State { ListView( children: [ //AppNameBar(), - SizedBox( - height: 16, - ), + const SizedBox(height: 16), Hero( tag: "logo", child: Image( height: _height / 6, - image: AssetImage("assets/images/logo.png"), + image: const AssetImage("assets/images/logo.png"), ), ), Center( child: Padding( padding: const EdgeInsets.all(8.0), child: Text( - _subtitle.newServiceRequest, + widget.serviceRequest == null ? _subtitle.newServiceRequest : _subtitle.updateServiceRequest, style: Theme.of(context).textTheme.headline5.copyWith(color: AColors.cyan, fontWeight: FontWeight.w600), ), ), @@ -107,24 +129,49 @@ class _CreateRequestPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ 12.height, - _userProvider.user.hospital == null - ? SizedBox.shrink() + _userProvider.user.clientId == null + ? const SizedBox.shrink() : ATextFormField( enable: false, - initialValue: _userProvider.user.hospital?.name ?? _subtitle.noHospitalFound, + initialValue: _userProvider.user.clientName ?? _subtitle.noHospitalFound, hintText: _subtitle.hospital, prefixIconData: FontAwesomeIcons.hospital, style: Theme.of(context).textTheme.subtitle1, ), 12.height, - _userProvider.user.department == null - ? SizedBox.shrink() - : ATextFormField( - enable: false, - initialValue: _userProvider.user.department?.name ?? _subtitle.noUniteFound, - hintText: _subtitle.unite, - prefixIconData: FontAwesomeIcons.hospitalUser, - style: Theme.of(context).textTheme.subtitle1, + _userProvider.user.departmentId == null || (_userProvider.user?.departmentId?.isEmpty ?? false) + ? const SizedBox.shrink() + : Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: const Color(0xfff5f5f5), + border: Border.all( + color: const Color(0xffefefef), + ), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: _userProvider.user.departmentName + ?.map( + (e) => Text( + e?.trim() ?? "", + style: Theme.of(context).textTheme.titleMedium.copyWith(color: AColors.black), + ), + ) + ?.toList() ?? + [], + ), + Icon( + FontAwesomeIcons.hospitalUser, + size: 20 * AppStyle.getScaleFactor(context), + color: const Color(0xff2e303a), + ), + ], + ), ), 12.height, DeviceButton( @@ -134,71 +181,207 @@ class _CreateRequestPageState extends State { setState(() {}); }, ), - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), const ASubTitle("Priority"), - const SizedBox(height: 4,), + const SizedBox( + height: 4, + ), ServiceRequestPriorityMenu( initialValue: _serviceRequest.priority, - onSelect: (status){ + onSelect: (status) { _serviceRequest.priority = status; }, + enabled: widget.serviceRequest == null ? true : false, + ), + const SizedBox( + height: 8, + ), + const ASubTitle("Equipment Status"), + const SizedBox( + height: 4, ), - const SizedBox(height: 8,), - const ASubTitle("Defect Type"), - const SizedBox(height: 4,), ServiceRequestDefectTypesMenu( initialValue: _serviceRequest.defectType, - onSelect: (status){ + onSelect: (status) { _serviceRequest.defectType = status; }, + enabled: widget.serviceRequest == null ? true : false, ), 12.height, - MultiImagesPicker( - label: _subtitle.deviceImages, - images: _deviceImages, + const SizedBox( + height: 8, + ), + const ASubTitle("Type of Request"), + const SizedBox( + height: 4, + ), + ServiceRequestTypesMenu( + initialValue: _serviceRequest.type, + onSelect: (status) { + _serviceRequest.type = status; + }, + enabled: false, + withDefaultItem: widget.serviceRequest == null, + ), + const SizedBox( + height: 8, + ), + const ASubTitle("Through"), + const SizedBox( + height: 4, + ), + ServiceRequestedThroughMenu( + initialValue: _serviceRequest.requestedThrough, + enabled: false, + ), + if (widget.serviceRequest != null) 12.height, + if (widget.serviceRequest != null) const ASubTitle("First Action"), + const SizedBox( + height: 4, + ), + if (widget.serviceRequest != null) + ServiceRequestedFirstAction( + initialValue: _serviceRequest.firstAction, + onSelect: (status) { + _dateTime = null; + _serviceRequest.firstAction = status; + _showDatePicker = _serviceRequest.firstAction != null && _serviceRequest.firstAction.name == "Need a visit"; + _serviceRequestsProvider.notifyListeners(); + }, + ), + if (_showDatePicker) 12.height, + if (_showDatePicker) + ADatePicker( + date: _dateTime, + from: DateTime.now(), + onDatePicker: (date) { + _dateTime = date; + setState(() {}); + }, + ), + if (widget.serviceRequest != null) 12.height, + if (widget.serviceRequest != null) const ASubTitle("Loan Availability"), + const SizedBox( + height: 4, + ), + if (widget.serviceRequest != null) + ServiceRequestedLoanAvailability( + initialValue: _serviceRequest.loanAvailability, + onSelect: (status) { + _serviceRequest.loanAvailability = status; + }, + ), + 12.height, + if (widget.serviceRequest != null) const ASubTitle("Comments"), + const SizedBox( + height: 4, + ), + if (widget.serviceRequest != null) + ATextFormField( + controller: _reviewCommentController, + initialValue: _serviceRequest.reviewComment, + hintText: _subtitle.comment, + style: Theme.of(context).textTheme.titleMedium, + textInputType: TextInputType.multiline, + onSaved: (value) { + _serviceRequest.reviewComment = value; + }, + enable: widget.serviceRequest != null ? false : true, + ), + 12.height, + MultiFilesPicker( + label: _subtitle.deviceFiles, + files: _deviceImages, + enabled: widget.serviceRequest == null ? true : false, ), 12.height, - SpeechToTextButton(controller: _controller), + SpeechToTextButton( + controller: _maintenanceController, + enabled: widget.serviceRequest == null ? true : false, + ), 12.height, ATextFormField( - controller: _controller, - initialValue: _serviceRequest.maintenanceIssue, + controller: _maintenanceController, + initialValue: _serviceRequest.callComments, hintText: _subtitle.maintenanceIssue, prefixIconData: FontAwesomeIcons.triangleExclamation, - style: Theme.of(context).textTheme.headline6, + style: Theme.of(context).textTheme.titleLarge, textInputType: TextInputType.multiline, validator: (value) => Validator.hasValue(value) ? null : _subtitle.maintenanceIssueRequired, onSaved: (value) { - _serviceRequest.maintenanceIssue = value; + _serviceRequest.callComments = value; }, + enable: widget.serviceRequest == null ? true : false, ), 12.height, - RecordSound(onRecord: (audio) { - _serviceRequest.audio = audio; - }), + RecordSound( + onRecord: (audio) { + _serviceRequest.audio = audio; + }, + enabled: widget.serviceRequest == null ? true : false, + ), 12.height, + if (widget.serviceRequest != null) + ATextFormField( + controller: _commentController, + initialValue: _serviceRequest.comments, + hintText: _subtitle.comment, + style: Theme.of(context).textTheme.titleMedium, + textInputType: TextInputType.multiline, + onSaved: (value) { + _serviceRequest.comments = value; + }, + ), ], ).paddingOnly(left: 20, right: 20), Padding( padding: const EdgeInsets.all(20.0), child: AButton( - text: _subtitle.submit, + text: widget.serviceRequest == null ? _subtitle.submit : _subtitle.update, onPressed: () async { if (!_formKey.currentState.validate()) return; + if (_device?.id == null) { + Fluttertoast.showToast(msg: _subtitle.pickDevice); + return; + } + if (_serviceRequest.firstAction?.name == "Need a visit" && _dateTime == null) { + Fluttertoast.showToast(msg: _subtitle.noDateFound); + return; + } + if (widget.serviceRequest != null && (_serviceRequest?.engineerId == null || (_serviceRequest?.engineerId?.isEmpty ?? false))) { + await Fluttertoast.showToast(msg: "No Assigned Employee"); + return; + } _formKey.currentState.save(); - _serviceRequest.deviceId = _device?.id ?? ""; + _serviceRequest.deviceId = _device?.id; + if (widget.serviceRequest == null) { + _serviceRequest.type = Provider.of(context, listen: false).getDefaultItem(); + } + _serviceRequest.requestedThrough = Provider.of(context, listen: false).getDefaultItem(); _isLoading = true; setState(() {}); - _serviceRequest.devicePhotos = _deviceImages.map((e) => base64Encode(e.readAsBytesSync())).toList(); + _serviceRequest.devicePhotos = _deviceImages.map((e) => "${e.path.split("/").last}|${base64Encode(e.readAsBytesSync())}").toList(); if (_serviceRequest.audio != null) { final file = File(_serviceRequest.audio); - _serviceRequest.audio = base64Encode(file.readAsBytesSync()); + _serviceRequest.audio = "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}"; + } + int status = 0; + if (widget.serviceRequest == null) { + status = await _serviceRequestsProvider.createRequest( + user: _userProvider.user, + host: _settingProvider.host, + serviceRequest: _serviceRequest, + ); + } else { + status = await _serviceRequestsProvider.updateDate( + user: _userProvider.user, + host: _settingProvider.host, + request: _serviceRequest, + date: _dateTime, + ); } - int status = await _serviceRequestsProvider.createRequest( - user: _userProvider.user, - host: _settingProvider.host, - serviceRequest: _serviceRequest, - ); _isLoading = false; setState(() {}); if (status >= 200 && status < 300) { @@ -217,7 +400,7 @@ class _CreateRequestPageState extends State { ), ], ), - ABackButton(), + const ABackButton(), ], ), ), diff --git a/lib/views/pages/user/requests/future_request_service_details.dart b/lib/views/pages/user/requests/future_request_service_details.dart index 7f56dd5f..6a09ae35 100644 --- a/lib/views/pages/user/requests/future_request_service_details.dart +++ b/lib/views/pages/user/requests/future_request_service_details.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; @@ -7,8 +9,7 @@ import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/pages/user/requests/request_details.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; import 'package:test_sa/views/widgets/loaders/failed_loading.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; + class FutureRequestServiceDetails extends StatefulWidget { static final String id = "/service-request-details"; @@ -17,9 +18,9 @@ class FutureRequestServiceDetails extends StatefulWidget { } class _FutureRequestServiceDetailsState extends State { - UserProvider _userProvider; SettingProvider _settingProvider; + @override Widget build(BuildContext context) { _userProvider = Provider.of(context); @@ -28,19 +29,16 @@ class _FutureRequestServiceDetailsState extends State( - future: ServiceRequestsProvider().getSingleServiceRequest( - requestId: requestId, - user: _userProvider.user, - host: _settingProvider.host, - subtitle: _subtitle - ), - builder: (BuildContext context, AsyncSnapshot snapshot){ - if(snapshot.hasError) + future: ServiceRequestsProvider().getSingleServiceRequest(requestId: requestId, user: _userProvider.user, host: _settingProvider.host, subtitle: _subtitle), + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.hasError) return FailedLoading( message: snapshot.error.toString(), - onReload: (){setState(() {});}, + onReload: () { + setState(() {}); + }, ); - if(snapshot.hasData){ + if (snapshot.hasData) { return RequestDetailsPage( serviceRequest: snapshot.data, ); diff --git a/lib/views/pages/user/requests/report/create_service_report.dart b/lib/views/pages/user/requests/report/create_service_report.dart index b9f353be..ff09c44c 100644 --- a/lib/views/pages/user/requests/report/create_service_report.dart +++ b/lib/views/pages/user/requests/report/create_service_report.dart @@ -1,81 +1,81 @@ import 'dart:convert'; import 'dart:io'; -import 'package:test_sa/controllers/http_status_manger/http_status_manger.dart'; +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/localization/localization.dart'; -import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart'; import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/controllers/validator/validator.dart'; -import 'package:test_sa/models/device/device.dart'; +import 'package:test_sa/models/call_request_for_work_order_model.dart'; +import 'package:test_sa/models/engineer.dart'; import 'package:test_sa/models/part.dart'; import 'package:test_sa/models/service_report.dart'; import 'package:test_sa/models/service_request/service_request.dart'; -import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; -import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; +import 'package:test_sa/views/widgets/e_signature/e_signature.dart'; import 'package:test_sa/views/widgets/equipment/auto_complete_devices_field.dart'; import 'package:test_sa/views/widgets/images/mini_one_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/parts/auto_complete_parts_field.dart'; import 'package:test_sa/views/widgets/parts/part_item.dart'; -import 'package:test_sa/views/widgets/speech_to_text/speech_to_text.dart'; +import 'package:test_sa/views/widgets/status/report/service_report_equipment_status.dart'; import 'package:test_sa/views/widgets/status/report/service_report_last_call.dart'; import 'package:test_sa/views/widgets/status/report/service_report_reasons.dart'; -import 'package:test_sa/views/widgets/status/report/service_report_status.dart'; -import 'package:test_sa/views/widgets/status/report/service_report_type.dart'; -import 'package:test_sa/views/widgets/status/report/service_status.dart'; -import 'package:test_sa/views/widgets/timer/app_timer.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; -import 'package:fluttertoast/fluttertoast.dart'; -import 'package:provider/provider.dart'; + +import '../../../../../controllers/providers/api/status_drop_down/report/service_types_provider.dart'; +import '../../../../widgets/date_and_time/date_picker.dart'; +import '../../../../widgets/status/report/service_report_fault_description.dart'; +import '../../../../widgets/status/report/service_report_repair_location.dart'; +import '../../../../widgets/timer/app_timer.dart'; + class CreateServiceReport extends StatefulWidget { static final String id = "/create-service-report"; - final ServiceRequest request ; + final ServiceRequest request; const CreateServiceReport({Key key, this.request}) : super(key: key); + @override _CreateServiceReportState createState() => _CreateServiceReportState(); } -class _CreateServiceReportState extends State with TickerProviderStateMixin{ - - +class _CreateServiceReportState extends State with TickerProviderStateMixin { UserProvider _userProvider; SettingProvider _settingProvider; ServiceRequestsProvider _serviceRequestsProvider; - + ServiceStatusProvider _assetTypeProvider; bool _validate = false; ServiceReport _serviceReport; bool _isLoading = false; + bool _showCommentField = false; Subtitle _subtitle; File _image; final GlobalKey _formKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); - TextEditingController _faultController = TextEditingController(); - TextEditingController _workPreformedController = TextEditingController(); + final TextEditingController _faultController = TextEditingController(); + final TextEditingController _workPreformedController = TextEditingController(); @override void initState() { _serviceReport = ServiceReport( - visitDate: DateTime.now(), - type: const Lookup(id: 2), - device: Device( - id: widget.request.deviceId, - serialNumber: widget.request.deviceSerialNumber, - ), - parts: [] + returnToService: DateTime.now(), + //type: const Lookup(value: 2), + device: widget.request.device, + parts: [], ); super.initState(); + // _isLoading = true; } @override @@ -84,11 +84,32 @@ class _CreateServiceReportState extends State with TickerPr _workPreformedController.dispose(); super.dispose(); } + + CallRequestForWorkOrder _callRequestForWorkOrder; + + void getRequestForWorkOrder() async { + _isLoading = true; + setState(() {}); + _callRequestForWorkOrder = await _serviceRequestsProvider.getCallRequestForWorkOrder(callId: widget.request.id); + _serviceReport.engineer = Engineer.fromJson(_callRequestForWorkOrder?.assignedEmployee?.toJson()); + await _assetTypeProvider.getTypes(user: _userProvider.user, host: _settingProvider.host); + _isLoading = false; + setState(() {}); + } + @override Widget build(BuildContext context) { _userProvider = Provider.of(context); _settingProvider = Provider.of(context); _serviceRequestsProvider = Provider.of(context); + _assetTypeProvider = Provider.of(context); + if (_callRequestForWorkOrder == null) { + getRequestForWorkOrder(); + } + _serviceReport.assetType = _assetTypeProvider.statuses?.firstWhere( + (element) => element.value == _callRequestForWorkOrder?.assetType, + orElse: () => null, + ); _subtitle = AppLocalization.of(context).subtitle; return Scaffold( key: _scaffoldKey, @@ -103,551 +124,834 @@ class _CreateServiceReportState extends State with TickerPr child: Stack( children: [ ListView( + padding: const EdgeInsets.all(16), children: [ //AppNameBar(), - const SizedBox(height: 16,), + const SizedBox( + height: 16, + ), Center( child: Padding( padding: const EdgeInsets.all(8.0), child: Text( _subtitle.newServiceReport, - style: Theme.of(context).textTheme.headline5.copyWith( - color: AColors.cyan, - fontSize: 28, - fontWeight: FontWeight.bold - ), + style: Theme.of(context).textTheme.headline5.copyWith(color: AColors.cyan, fontSize: 28, fontWeight: FontWeight.bold), ), ), ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 16), - margin: const EdgeInsets.symmetric(horizontal: 16,vertical: 16), - decoration: BoxDecoration( - color: AColors.grey, - borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), - boxShadow: [ - const BoxShadow( + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle("Caller Info"), + const SizedBox(height: 8), + Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 16), + decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: const [ + BoxShadow( color: AColors.grey, - offset: Offset(0,-1), + offset: Offset(0, -1), ) - ] - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 8,), - Wrap( + ]), + child: Wrap( + direction: Axis.vertical, spacing: 10, children: [ - ASubTitle("${_subtitle.callId}: ${widget.request.requestCode}",font: 14,), - widget.request.deviceSerialNumber == null ? const SizedBox(): - ASubTitle("${_subtitle.deviceSN}: ${widget.request.deviceSerialNumber}",font: 14,), + ASubTitle( + "${_subtitle.callId}: ${widget.request.requestCode}", + font: 14, + ), + ASubTitle( + "${_subtitle.assetNumber}: ${widget.request.deviceNumber}", + font: 14, + ), + widget.request.deviceSerialNumber == null + ? const SizedBox() + : ASubTitle( + "${_subtitle.deviceSN}: ${widget.request.deviceSerialNumber}", + font: 14, + ), Text( "${_subtitle.customer}: ${widget.request.hospitalName}", style: Theme.of(context).textTheme.subtitle1.copyWith( - fontWeight: FontWeight.bold, - fontSize: 12, - ), + fontWeight: FontWeight.bold, + fontSize: 12, + ), textScaleFactor: AppStyle.getScaleFactor(context), ) - ], ), - const Divider(), + ), - // Report type and Reasons - Row( - children: [ - // Report Status - // Expanded( - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // ASubTitle(_subtitle.reportType), - // _validate && _serviceReport.type == null ? - // ASubTitle(_subtitle.requiredWord,color: Colors.red,): - // const SizedBox.shrink(), - // const SizedBox(height: 4,), - // ServiceReportTypeMenu( - // initialValue: _serviceReport.type, - // onSelect: (status){ - // _serviceReport.type = status; - // }, - // ), - // ], - // ), - // ), - // const SizedBox(width: 8,), - // visit date - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.visitDate), - _validate && _serviceReport.visitDate == null ? - ASubTitle(_subtitle.requiredWord,color: Colors.red,): - const SizedBox.shrink(), - Row( - children: [ - Expanded( - child: ADatePicker( - date: _serviceReport.visitDate, - from: DateTime.now().subtract(const Duration(days: 365)), - to: DateTime.now().add(const Duration(days: 365)), - onDatePicker: (date){ - _serviceReport.visitDate = date; - setState(() {}); - }, - ), - ), - ], - ), - ], - ), - ), - - ], - ), - const SizedBox(height: 8,), - // device sn - Visibility( - visible: widget.request.deviceSerialNumber == null, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.deviceSN), - _validate && _serviceReport.device?.id == null ? - ASubTitle(_subtitle.requiredWord,color: Colors.red,): - const SizedBox.shrink(), - AutoCompleteDeviceField( - hospitalId: widget.request.hospitalId, - initialValue: _serviceReport.device, - onPick: (id){ - _serviceReport.device.id = id; - }, - ), - const SizedBox(height: 8,), - ], + ASubTitle("Work Order Details"), + Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 16), + decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [ + BoxShadow( + color: AColors.grey, + offset: Offset(0, -1), ), - ), - const SizedBox(height: 8,), - ASubTitle(_subtitle.serviceType), - _validate && _serviceReport.serviceType == null ? - ASubTitle(_subtitle.requiredWord,color: Colors.red,): - const SizedBox.shrink(), - const SizedBox(height: 4,), - ServiceStatusMenu( - initialValue: _serviceReport.serviceType, - onSelect: (status){ - _serviceReport.serviceType = status; - }, - ), - const SizedBox(height: 8,), - // Report status and Service Type - Row( + ]), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - // report status - Expanded( + // Report type and Reasons + // device sn + Visibility( + visible: widget.request.deviceSerialNumber == null, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - ASubTitle(_subtitle.reportStatus), - _validate && _serviceReport.status == null ? - ASubTitle(_subtitle.requiredWord,color: Colors.red,): - const SizedBox.shrink(), - const SizedBox(height: 4,), - ServiceReportStatusMenu( - report: _serviceReport, - onSelect: (status){ - _serviceReport.status = status; + ASubTitle(_subtitle.deviceSN), + _validate && _serviceReport.device?.id == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + AutoCompleteDeviceField( + hospitalId: widget.request.hospitalId, + initialValue: _serviceReport.device, + onPick: (id) { + _serviceReport.device.id = id; }, ), - ], - ), - ), - const SizedBox(width: 8,), - Provider.of(context).isLoading == null - ? const SizedBox.shrink(): - // Call's last Situation - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - - ASubTitle(_subtitle.callLastSituation), - _validate && _serviceReport.callLastSituation == null ? - ASubTitle(_subtitle.requiredWord,color: Colors.red,): - const SizedBox.shrink(), - const SizedBox(height: 4,), - ServiceReportLastCallsMenu( - report: _serviceReport, - onSelect: (status){ - if(status?.id == 12 - || _serviceReport.callLastSituation?.id == 12){ - _serviceReport.callLastSituation = status; - setState(() {}); - } else { - _serviceReport.callLastSituation = status; - } - }, + const SizedBox( + height: 8, ), ], ), ), - ], - ), - const SizedBox(height: 8,), - // invoice number & code - _serviceReport.callLastSituation?.id != 12 ? const SizedBox.shrink(): - Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.invoiceNumber), - const SizedBox(height: 8,), - ATextFormField( - initialValue: _serviceReport?.invoiceNumber, - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - validator: (value) => - Validator.hasValue(value) - ? null : _subtitle.requiredWord, - textInputType: TextInputType.number, - onSaved: (value){ - _serviceReport.invoiceNumber = value; - }, - ), - ], - ), + const SizedBox( + height: 8, ), - const SizedBox(width: 8,), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.invoiceCode), - const SizedBox(height: 4,), - ATextFormField( - initialValue: _serviceReport?.invoiceCode, - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - validator: (value) => - Validator.hasValue(value) - ? null : _subtitle.requiredWord, - textInputType: TextInputType.text, - onSaved: (value){ - _serviceReport.invoiceCode = value; - }, - ), - ], - ), + ASubTitle(_subtitle.assetType ?? ""), + _validate && _serviceReport.assetType == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + const SizedBox( + height: 4, ), - ], - ), - const SizedBox(height: 8,), - Row( - children: [ - ASubTitle(_subtitle.faultDescription), - Expanded( - child: SizedBox( - height: 32 * AppStyle.getScaleFactor(context), - child: SpeechToTextButton( - controller: _faultController, - mini: true, - ), + LoadingManager( + isLoading: _assetTypeProvider.isLoading, + isFailedLoading: _assetTypeProvider.statuses == null, + stateCode: _assetTypeProvider.stateCode, + onRefresh: () async { + _assetTypeProvider.reset(); + await _assetTypeProvider.getTypes(user: _userProvider.user, host: _settingProvider.host); + _serviceReport?.assetType = _assetTypeProvider.statuses?.firstWhere( + (element) => element.value == _callRequestForWorkOrder.assetType, + orElse: () => null, + ); + }, + child: ATextFormField( + initialValue: _serviceReport?.assetType?.name ?? "NULL", + textAlign: TextAlign.center, + enable: false, + style: Theme.of(context).textTheme.titleMedium, ), ), - ], - ), - const SizedBox(height: 4,), - ATextFormField( - initialValue: _serviceReport?.faultDescription, - textAlign: TextAlign.center, - controller: _faultController, - style: Theme.of(context).textTheme.subtitle1, - validator: (value) => - Validator.hasValue(value) - ? null : _subtitle.requiredWord, - textInputType: TextInputType.multiline, - onSaved: (value){ - _serviceReport.faultDescription = value; - }, - ), - const SizedBox(height: 8,), - Row( - children: [ - ASubTitle(_subtitle.workPreformed), - Expanded( - child: SizedBox( - height: 32 * AppStyle.getScaleFactor(context), - child: SpeechToTextButton( - controller: _workPreformedController, - mini: true, - ), - ), + // ServiceAssetTypeMenu( + // initialValue: _serviceReport.assetType, + // onSelect: (status) { + // _serviceReport.assetType = status; + // }, + // ), + const SizedBox( + height: 8, ), - ], - ), - const SizedBox(height: 4,), - ATextFormField( - initialValue: _serviceReport?.workPreformed, - textAlign: TextAlign.center, - controller: _workPreformedController, - style: Theme.of(context).textTheme.subtitle1, - validator: (value) => - Validator.hasValue(value) - ? null : _subtitle.requiredWord, - textInputType: TextInputType.multiline, - onSaved: (value){ - _serviceReport.workPreformed = value; - }, - ), - const SizedBox(height: 8,), - - const SizedBox(height: 8,), - Row( - children: [ - // reasons - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.reasons), - const SizedBox(height: 4,), - ServiceReportReasonsMenu( - initialValue: _serviceReport.reason, - onSelect: (status){ - _serviceReport.reason = status; - }, + // Report status and Asset Type + Row( + children: [ + // report status + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // ASubTitle(_subtitle.reportStatus), + ASubTitle("Equipment Status"), + _validate && _serviceReport.equipmentStatus == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + const SizedBox( + height: 4, + ), + // ServiceReportStatusMenu( + // report: _serviceReport, + // request: widget.request, + // onSelect: (status) { + // _serviceReport.status = status; + // }, + // ), + ServiceReportEquipmentStatusMenu( + report: _serviceReport, + request: widget.request, + onSelect: (status) { + _serviceReport.equipmentStatus = status; + }, + ) + ], ), - ], - ), + ), + const SizedBox( + width: 8, + ), + // Provider.of(context).isLoading == null + // ? const SizedBox.shrink(): + // Call's last Situation + Consumer( + builder: (_, provider, __) { + if (provider.isLoading == null) return const SizedBox.shrink(); + return Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(_subtitle.callLastSituation), + _validate && _serviceReport.callLastSituation == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + const SizedBox( + height: 4, + ), + ServiceReportLastCallsMenu( + report: _serviceReport, + onSelect: (status) { + if (status?.value == 12 || _serviceReport.callLastSituation?.value == 12) { + _serviceReport.callLastSituation = status; + setState(() {}); + } else { + _serviceReport.callLastSituation = status; + } + }, + ), + ], + ), + ); + }, + ), + ], ), - const SizedBox(width: 8,), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.attachImage), - AMiniOneImagePicker( - //error: _validate && _serviceReport.image == null, - image: _image, - onPick: (image){ - _image =image; - _serviceReport.image = base64Encode(image.readAsBytesSync()); - }, + // if (_showCommentField) + // const SizedBox( + // height: 8, + // ), + // if (_showCommentField) + // ATextFormField( + // initialValue: _serviceReport?.reviewComment, + // hintText: "Review Comment", + // textAlign: TextAlign.center, + // style: Theme.of(context).textTheme.titleMedium, + // textInputType: TextInputType.multiline, + // onSaved: (value) { + // _serviceReport.reviewComment = value; + // }, + // ), + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), + ), + Row( + children: [ + // Report Status + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // ASubTitle(_subtitle.reportType), + // _validate && _serviceReport.type == null ? + // ASubTitle(_subtitle.requiredWord,color: Colors.red,): + // const SizedBox.shrink(), + // const SizedBox(height: 4,), + // ServiceReportTypeMenu( + // initialValue: _serviceReport.type, + // onSelect: (status){ + // _serviceReport.type = status; + // }, + // ), + // ], + // ), + // ), + // const SizedBox(width: 8,), + // visit date + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ASubTitle("Return to Service"), + _validate && _serviceReport.returnToService == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + Row( + children: [ + Expanded( + child: ADatePicker( + date: _serviceReport.returnToService, + from: DateTime.now().subtract(const Duration(days: 365)), + to: DateTime.now().add(const Duration(days: 365)), + onDatePicker: (date) { + _serviceReport.returnToService = date; + setState(() {}); + }, + ), + ), + ], + ), + ], ), - ], - ), + ), + ], ), - ], - ), - const SizedBox(height: 8,), - // Traveling Hours & Working Hours - Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.workingHours), - const SizedBox(height: 8,), - AppTimer( + const SizedBox( + height: 8, + ), + ASubTitle(_subtitle.workingHours), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: AppTimer( timer: _serviceReport.timer, - onChange: (timer) async{ + onChange: (timer) async { _serviceReport.timer = timer; + _serviceReport.workingHours = num.tryParse((((timer?.durationInSecond ?? 0) / 60) / 60)?.toStringAsFixed(2) ?? "0"); return true; }, ), - // ATextFormField( - // initialValue: _serviceReport?.workHours, - // textAlign: TextAlign.center, - // hintText: "i.e 3, 3.5, 4", - // style: Theme.of(context).textTheme.subtitle1, - // validator: (value) => - // Validator.isNumeric(value) - // ? null : _subtitle.requiredWord, - // textInputType: TextInputType.number, - // onSaved: (value){ - // _serviceReport.workHours = value; - // }, - // ), - ], - ), + ), + ], ), - const SizedBox(width: 8,), - Expanded( + const SizedBox(height: 16), + // device sn + Visibility( + visible: widget.request.deviceSerialNumber == null, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - ASubTitle(_subtitle.travelingHours), - const SizedBox(height: 4,), - ATextFormField( - initialValue: _serviceReport?.travelingHours, - textAlign: TextAlign.center, - hintText: "i.e 3, 3.5, 4", - style: Theme.of(context).textTheme.subtitle1, - // validator: (value) => - // Validator.isNumeric(value) - // ? null : _subtitle.requiredWord, - textInputType: TextInputType.number, - onSaved: (value){ - _serviceReport.travelingHours = value; + ASubTitle(_subtitle.deviceSN), + _validate && _serviceReport.device?.id == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + AutoCompleteDeviceField( + hospitalId: widget.request.hospitalId, + initialValue: _serviceReport.device, + onPick: (id) { + _serviceReport.device.id = id; }, ), + const SizedBox( + height: 8, + ), ], ), ), - ], - ), - const SizedBox(height: 8,), - // Operating Hours and Job Sheet Number - Row( - children: [ - // Expanded( - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // ASubTitle(_subtitle.operatingHours), - // const SizedBox(height: 4,), - // ATextFormField( - // initialValue: _serviceReport?.operatingHours, - // textAlign: TextAlign.center, - // hintText: "i.e 3, 3.5, 4", - // style: Theme.of(context).textTheme.subtitle1, - // validator: (value) => - // Validator.isNumeric(value) - // ? null : _subtitle.requiredWord, - // textInputType: TextInputType.number, - // onSaved: (value){ - // _serviceReport.operatingHours = value; - // }, - // ), - // ], - // ), + + // Report status and Asset Type + + if (_showCommentField) + const SizedBox( + height: 8, + ), + if (_showCommentField) + ATextFormField( + initialValue: _serviceReport?.reviewComment, + hintText: "Review Comment", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleMedium, + textInputType: TextInputType.multiline, + onSaved: (value) { + _serviceReport.reviewComment = value; + }, + ), + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), + ), + + // invoice number & code + _serviceReport.callLastSituation?.id != 12 + ? const SizedBox.shrink() + : Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(_subtitle.invoiceNumber), + const SizedBox( + height: 8, + ), + ATextFormField( + initialValue: _serviceReport?.invoiceNumber, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.subtitle1, + validator: (value) => Validator.hasValue(value) ? null : _subtitle.requiredWord, + textInputType: TextInputType.number, + onSaved: (value) { + _serviceReport.invoiceNumber = value; + }, + ), + ], + ), + ), + const SizedBox( + width: 8, + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(_subtitle.invoiceCode), + const SizedBox( + height: 4, + ), + ATextFormField( + initialValue: _serviceReport?.invoiceCode, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.subtitle1, + validator: (value) => Validator.hasValue(value) ? null : _subtitle.requiredWord, + textInputType: TextInputType.text, + onSaved: (value) { + _serviceReport.invoiceCode = value; + }, + ), + ], + ), + ), + ], + ), + const SizedBox(height: 8), + ASubTitle(_subtitle.faultDescription), + const SizedBox( + height: 4, + ), + ServiceReportFaultDescription( + requestId: widget.request?.id, + initialValue: _serviceReport.faultDescription, + enabled: false, + onSelect: (status) { + _serviceReport.faultDescription = status; + setState(() {}); + }, + ), + const SizedBox( + height: 4, + ), + // ATextFormField( + // initialValue: _serviceReport?.faultDescriptionId?.toString(), + // textAlign: TextAlign.center, + // controller: _faultController, + // style: Theme.of(context).textTheme.titleMedium, + // validator: (value) => Validator.hasValue(value) ? null : _subtitle.requiredWord, + // textInputType: TextInputType.multiline, + // onSaved: (value) { + // _serviceReport.faultDescriptionId = int.tryParse(value) ?? 0; + // }, // ), - // const SizedBox(width: 8,), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.jobSheetNumber), - const SizedBox(height: 4,), - ATextFormField( - initialValue: _serviceReport?.jobSheetNumber, - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - textInputType: TextInputType.name, - onSaved: (value){ - _serviceReport.jobSheetNumber = value; - }, + const SizedBox( + height: 8, + ), + Row( + children: [ + const ASubTitle("Solutions"), + // Expanded( + // child: SizedBox( + // height: 32 * AppStyle.getScaleFactor(context), + // child: SpeechToTextButton( + // controller: _workPreformedController, + // mini: true, + // ), + // ), + // ), + ], + ), + const SizedBox( + height: 4, + ), + ATextFormField( + initialValue: _serviceReport?.workPreformed, + textAlign: TextAlign.center, + enable: false, + hintText: _serviceReport.faultDescription?.workPerformed ?? "", + controller: _workPreformedController, + style: Theme.of(context).textTheme.titleMedium, + validator: (value) => Validator.hasValue(value) ? null : _subtitle.requiredWord, + textInputType: TextInputType.multiline, + onSaved: (value) { + _serviceReport.workPreformed = value; + }, + ), + const SizedBox( + height: 8, + ), + + const SizedBox(height: 8), + Row( + children: [ + // reasons + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ASubTitle("Failure Reason"), + _validate && _serviceReport.reason?.id == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + const SizedBox(height: 4), + ServiceReportReasonsMenu( + initialValue: _serviceReport.reason, + onSelect: (status) { + _serviceReport.reason = status; + }, + ), + ], ), - ], - ), + ), + const SizedBox(width: 8), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(_subtitle.attachImage), + AMiniOneImagePicker( + //error: _validate && _serviceReport.image == null, + image: _image, + onPick: (image) { + _image = image; + _serviceReport.image[0] = "${image.path.split("/").last}|${base64Encode(image.readAsBytesSync())}"; + }, + ), + ], + ), + ), + ], ), - ], - ), - const SizedBox(height: 8,), - // Part Number and Quantity - Row( - children: [ - Expanded( - flex: 3, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.partNumber), - _validate && _serviceReport.parts == null ? - ASubTitle(_subtitle.requiredWord,color: Colors.red,): - const SizedBox.shrink(), - const SizedBox(height: 4,), - AutoCompletePartsField( - onPick: (part){ - _serviceReport.parts.add(part); - }, + const SizedBox(height: 8), + ASubTitle(_subtitle.repairLocation), + const SizedBox(height: 4), + ServiceReportRepairLocation( + initialValue: _serviceReport.repairLocation, + onSelect: (status) { + _serviceReport.repairLocation = status; + }, + ), + const SizedBox(height: 16), + const ASubTitle("Travel Expenses"), + const SizedBox( + height: 4, + ), + ATextFormField( + initialValue: _serviceReport?.travelingExpense?.toString(), + hintText: "i.e 3, 3.5, 4", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleMedium, + textInputType: TextInputType.number, + onSaved: (value) { + _serviceReport.travelingExpense = int.tryParse(value) ?? 0; + }, + ), + + const SizedBox( + height: 8, + ), + // Traveling Hours & Working Hours + Row( + children: [ + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // ASubTitle(_subtitle.workingHours), + // const SizedBox( + // height: 8, + // ), + // Row( + // children: [ + // Expanded( + // child: AppTimer( + // timer: _serviceReport.timer, + // onChange: (timer) async { + // _serviceReport.timer = timer; + // return true; + // }, + // ), + // ), + // ], + // ), + // // ATextFormField( + // // initialValue: _serviceReport?.workHours, + // // textAlign: TextAlign.center, + // // hintText: "i.e 3, 3.5, 4", + // // style: Theme.of(context).textTheme.subtitle1, + // // validator: (value) => + // // Validator.isNumeric(value) + // // ? null : _subtitle.requiredWord, + // // textInputType: TextInputType.number, + // // onSaved: (value){ + // // _serviceReport.workHours = value; + // // }, + // // ), + // ], + // ), + // ), + // const SizedBox(width: 8,), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(_subtitle.travelingHours), + const SizedBox( + height: 4, + ), + ATextFormField( + initialValue: _serviceReport?.travelingHours?.toString(), + textAlign: TextAlign.center, + hintText: "i.e 3, 3.5, 4", + style: Theme.of(context).textTheme.subtitle1, + // validator: (value) => + // Validator.isNumeric(value) + // ? null : _subtitle.requiredWord, + textInputType: TextInputType.number, + onSaved: (value) { + _serviceReport.travelingHours = double.tryParse(value) ?? 0.0; + }, + ), + ], ), - ], - ), + ), + ], ), + const SizedBox( + height: 8, + ), + // Operating Hours and Job Sheet Number + // Row( + // children: [ + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // ASubTitle(_subtitle.operatingHours), + // const SizedBox(height: 4,), + // ATextFormField( + // initialValue: _serviceReport?.operatingHours, + // textAlign: TextAlign.center, + // hintText: "i.e 3, 3.5, 4", + // style: Theme.of(context).textTheme.subtitle1, + // validator: (value) => + // Validator.isNumeric(value) + // ? null : _subtitle.requiredWord, + // textInputType: TextInputType.number, + // onSaved: (value){ + // _serviceReport.operatingHours = value; + // }, + // ), + // ], + // ), + // ), + // const SizedBox(width: 8,), + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // ASubTitle(_subtitle.jobSheetNumber), + // const SizedBox(height: 4,), + // ATextFormField( + // initialValue: _serviceReport?.jobSheetNumber, + // textAlign: TextAlign.center, + // style: Theme.of(context).textTheme.subtitle1, + // textInputType: TextInputType.name, + // onSaved: (value){ + // _serviceReport.jobSheetNumber = value; + // }, + // ), + // ], + // ), + // ), + // ], + // ), + const SizedBox(height: 8), + const ASubTitle("Technical comment"), + const SizedBox(height: 4), + ATextFormField( + initialValue: _serviceReport?.comment, + hintText: "Technical Comment", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleMedium, + textInputType: TextInputType.multiline, + onSaved: (value) { + _serviceReport.comment = value; + }, + ), + const SizedBox(height: 8), + const ASubTitle("Nurse Signature"), + ESignature( + oldSignature: _serviceReport.signatureNurse, + newSignature: _serviceReport.localNurseSignature, + onSaved: (signature) { + if (signature == null || signature.isEmpty) { + return; + } + _serviceReport.localNurseSignature = signature; + _serviceReport.signatureNurse = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + }, + ), + const SizedBox(height: 8), + const ASubTitle("Engineer Signature"), + ESignature( + oldSignature: _serviceReport.signatureEngineer, + newSignature: _serviceReport.localNurseSignature, + onSaved: (signature) { + if (signature == null || signature.isEmpty) { + return; + } + _serviceReport.localNurseSignature = signature; + _serviceReport.signatureEngineer = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + }, + ), + const SizedBox( + height: 8, + ), ], ), - SizedBox(height: 8*AppStyle.getScaleFactor(context),), - Row( + ), + + // Part Number and Quantity + ASubTitle("Spare Parts"), + Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 16), + decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [ + BoxShadow( + color: AColors.grey, + offset: Offset(0, -1), + ) + ]), + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Expanded(flex:3,child: Text(_subtitle.number)), - Expanded(flex: 1,child: Text(_subtitle.quantity)), - ], - ), - Column( - children: List.generate( - _serviceReport.parts.length, - (index) { - Part _part = _serviceReport.parts[index]; + Row( + children: [ + Expanded( + flex: 3, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(_subtitle.partNumberName), + _validate && _serviceReport.parts == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + const SizedBox( + height: 4, + ), + AutoCompletePartsField( + onPick: (part) { + _serviceReport.parts.add(part); + }, + ), + ], + ), + ), + ], + ), + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), + ), + Row( + children: [ + Expanded(flex: 3, child: Text(_subtitle.number)), + Expanded(flex: 1, child: Text(_subtitle.quantity)), + ], + ), + Column( + children: List.generate(_serviceReport.parts.length, (index) { + Part part = _serviceReport.parts[index]; return PartItem( - part: _part, - onDelete: (part){ + part: part, + onDelete: (part) { _serviceReport.parts.remove(part); setState(() {}); }, ); - } - ), + }), + ), + const SizedBox( + height: 16, + ), + ], ), - - const SizedBox(height: 16,), - - ], - ), + ), + ], ), - Padding( - padding: const EdgeInsets.all(16.0), - child: AButton( - text: _subtitle.submit, - onPressed: () async { - _validate = true; - if(!_formKey.currentState.validate()){ - setState(() {}); - return; - } - if(!_serviceReport.validate()) return; - _formKey.currentState.save(); - - _isLoading =true; + AButton( + text: _subtitle.submit, + onPressed: () async { + _validate = true; + // if (!_formKey.currentState.validate()) { + // setState(() {}); + // return; + // } + if (!(await _serviceReport.validate())) { setState(() {}); + return; + } + _formKey.currentState.save(); + + _isLoading = true; + setState(() {}); - int status = await _serviceRequestsProvider.createServiceReport( - user: _userProvider.user, - host: _settingProvider.host, - report: _serviceReport, - request: widget.request + int status = await _serviceRequestsProvider.createServiceReport( + user: _userProvider.user, + host: _settingProvider.host, + report: _serviceReport, + request: widget.request, + ); + print(6); + print(status); + _isLoading = false; + setState(() {}); + if (status >= 200 && status < 300) { + Fluttertoast.showToast( + msg: _subtitle.requestCompleteSuccessfully, ); - _isLoading =false; - setState(() {}); - if(status >= 200 && status < 300){ - Fluttertoast.showToast( - msg: _subtitle.requestCompleteSuccessfully, - ); - Navigator.of(context).pop(); - Navigator.of(context).pop(); - }else{ - String errorMessage = HttpStatusManger.getStatusMessage( - status: status, subtitle: _subtitle); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - errorMessage - ), - ) - ); - } - }, - ), + Navigator.of(context).pop(); + Navigator.of(context).pop(); + } else { + String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(errorMessage), + )); + } + }, ), - const SizedBox(height: 300,) + const SizedBox( + height: 300, + ) ], ), const ABackButton(), diff --git a/lib/views/pages/user/requests/report/edit_service_report.dart b/lib/views/pages/user/requests/report/edit_service_report.dart index 0b268fc7..828e6b11 100644 --- a/lib/views/pages/user/requests/report/edit_service_report.dart +++ b/lib/views/pages/user/requests/report/edit_service_report.dart @@ -2,16 +2,18 @@ import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/http_status_manger/http_status_manger.dart'; +import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_types_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/controllers/validator/validator.dart'; +import 'package:test_sa/models/call_request_for_work_order_model.dart'; +import 'package:test_sa/models/engineer.dart'; import 'package:test_sa/models/part.dart'; import 'package:test_sa/models/service_report.dart'; import 'package:test_sa/models/service_request/service_request.dart'; @@ -22,32 +24,33 @@ import 'package:test_sa/views/widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; +import 'package:test_sa/views/widgets/e_signature/e_signature.dart'; import 'package:test_sa/views/widgets/equipment/auto_complete_devices_field.dart'; -import 'package:test_sa/views/widgets/images/mini_one_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/parts/auto_complete_parts_field.dart'; import 'package:test_sa/views/widgets/parts/part_item.dart'; -import 'package:test_sa/views/widgets/speech_to_text/speech_to_text.dart'; +import 'package:test_sa/views/widgets/status/report/service_report_equipment_status.dart'; +import 'package:test_sa/views/widgets/status/report/service_report_fault_description.dart'; import 'package:test_sa/views/widgets/status/report/service_report_last_call.dart'; import 'package:test_sa/views/widgets/status/report/service_report_reasons.dart'; -import 'package:test_sa/views/widgets/status/report/service_report_status.dart'; -import 'package:test_sa/views/widgets/status/report/service_report_type.dart'; -import 'package:test_sa/views/widgets/status/report/service_status.dart'; +import 'package:test_sa/views/widgets/status/report/service_report_repair_location.dart'; import 'package:test_sa/views/widgets/timer/app_timer.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; + +import '../../../../widgets/images/multi_image_picker.dart'; + class EditServiceReport extends StatefulWidget { static final String id = "/edit-service-report"; - final ServiceRequest request ; + final ServiceRequest request; final ServiceReport report; const EditServiceReport({Key key, this.request, this.report}) : super(key: key); + @override _EditServiceReportState createState() => _EditServiceReportState(); } -class _EditServiceReportState extends State with TickerProviderStateMixin{ - - +class _EditServiceReportState extends State with TickerProviderStateMixin { UserProvider _userProvider; SettingProvider _settingProvider; ServiceRequestsProvider _serviceRequestsProvider; @@ -55,31 +58,56 @@ class _EditServiceReportState extends State with TickerProvid bool _validate = false; ServiceReport _serviceReport; bool _isLoading = false; + bool _showCommentField = false; Subtitle _subtitle; - File _image; + final List _images = []; final GlobalKey _formKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); TextEditingController _faultController = TextEditingController(); TextEditingController _workPreformedController = TextEditingController(); + ServiceStatusProvider _assetTypeProvider; + + CallRequestForWorkOrder _callRequestForWorkOrder; + @override void initState() { _serviceReport = widget.report; super.initState(); } + void getRequestForWorkOrder() async { + _isLoading = true; + setState(() {}); + _callRequestForWorkOrder = await _serviceRequestsProvider.getCallRequestForWorkOrder(callId: widget.request.id); + _serviceReport.engineer = Engineer.fromJson(_callRequestForWorkOrder?.assignedEmployee?.toJson()); + await _assetTypeProvider.getTypes(user: _userProvider.user, host: _settingProvider.host); + _isLoading = false; + setState(() {}); + } + @override void dispose() { _faultController.dispose(); _workPreformedController.dispose(); super.dispose(); } + @override Widget build(BuildContext context) { _userProvider = Provider.of(context); _settingProvider = Provider.of(context); _serviceRequestsProvider = Provider.of(context); + + _assetTypeProvider = Provider.of(context); + if (_callRequestForWorkOrder == null) { + getRequestForWorkOrder(); + } + _serviceReport.assetType = _assetTypeProvider.statuses?.firstWhere( + (element) => element.value == _callRequestForWorkOrder?.assetType, + orElse: () => null, + ); _subtitle = AppLocalization.of(context).subtitle; return Scaffold( key: _scaffoldKey, @@ -94,455 +122,877 @@ class _EditServiceReportState extends State with TickerProvid child: Stack( children: [ ListView( + padding: const EdgeInsets.all(16), children: [ - //AppNameBar(), - const SizedBox(height: 16,), + const SizedBox(height: 16), Center( child: Padding( padding: const EdgeInsets.all(8.0), child: Text( _subtitle.editServiceReport, - style: Theme.of(context).textTheme.headline5.copyWith( - color: AColors.cyan, - fontSize: 28, - fontWeight: FontWeight.bold - ), + style: Theme.of(context).textTheme.headline5.copyWith(color: AColors.cyan, fontSize: 28, fontWeight: FontWeight.bold), ), ), ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 16), - margin: const EdgeInsets.symmetric(horizontal: 16,vertical: 16), - decoration: BoxDecoration( - color: AColors.grey, - borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), - boxShadow: [ - const BoxShadow( + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle("Caller Info"), + const SizedBox(height: 8), + Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 16), + decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: const [ + BoxShadow( color: AColors.grey, - offset: Offset(0,-1), + offset: Offset(0, -1), ) - ] - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 8,), - Wrap( + ]), + child: Wrap( + direction: Axis.vertical, spacing: 10, children: [ - ASubTitle("${_subtitle.callId}: ${widget.request.requestCode}",font: 14,), - widget.request.deviceSerialNumber == null ? const SizedBox(): - ASubTitle("${_subtitle.deviceSN}: ${widget.request.deviceSerialNumber}",font: 14,), + ASubTitle( + "${_subtitle.callId}: ${widget.request.requestCode}", + font: 14, + ), + ASubTitle( + "${_subtitle.assetNumber}: ${widget.request.deviceNumber}", + font: 14, + ), + widget.request.deviceSerialNumber == null + ? const SizedBox() + : ASubTitle( + "${_subtitle.deviceSN}: ${widget.request.deviceSerialNumber}", + font: 14, + ), Text( "${_subtitle.customer}: ${widget.request.hospitalName}", style: Theme.of(context).textTheme.subtitle1.copyWith( - fontWeight: FontWeight.bold, - fontSize: 12, - ), + fontWeight: FontWeight.bold, + fontSize: 12, + ), textScaleFactor: AppStyle.getScaleFactor(context), ) - ], ), - const Divider(), - - // Report type and Reasons - Row( + ), + const SizedBox(height: 8), + ASubTitle("Work Order Details"), + const SizedBox(height: 8), + Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 16), + decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: const [ + BoxShadow( + color: AColors.grey, + offset: Offset(0, -1), + ) + ]), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - // Report Status - Expanded( + // Report type and Reasons + // Row( + // children: [ + // // Report Status + // // Expanded( + // // child: Column( + // // crossAxisAlignment: CrossAxisAlignment.start, + // // children: [ + // // ASubTitle(_subtitle.reportType), + // // _validate && _serviceReport.type == null + // // ? ASubTitle( + // // _subtitle.requiredWord, + // // color: Colors.red, + // // ) + // // : const SizedBox.shrink(), + // // const SizedBox( + // // height: 4, + // // ), + // // ServiceReportTypeMenu( + // // initialValue: _serviceReport.type, + // // onSelect: (status) { + // // _serviceReport.type = status; + // // }, + // // ), + // // ], + // // ), + // // ), + // // const SizedBox( + // // width: 8, + // // ), + // // visit date + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // ASubTitle(_subtitle.visitDate), + // _validate && _serviceReport.visitDate == null + // ? ASubTitle( + // _subtitle.requiredWord, + // color: Colors.red, + // ) + // : const SizedBox.shrink(), + // Row( + // children: [ + // Expanded( + // child: ADatePicker( + // date: _serviceReport.visitDate, + // from: DateTime.now().subtract(const Duration(days: 365)), + // to: DateTime.now().add(const Duration(days: 365)), + // onDatePicker: (date) { + // _serviceReport.visitDate = date; + // setState(() {}); + // }, + // ), + // ), + // ], + // ), + // ], + // ), + // ), + // ], + // ), + // const SizedBox( + // height: 8, + // ), + // device sn + Visibility( + visible: widget.request.deviceSerialNumber == null, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - ASubTitle(_subtitle.reportType), - _validate && _serviceReport.type == null ? - ASubTitle(_subtitle.requiredWord,color: Colors.red,): - const SizedBox.shrink(), - const SizedBox(height: 4,), - ServiceReportTypeMenu( - initialValue: _serviceReport.type, - onSelect: (status){ - _serviceReport.type = status; + ASubTitle(_subtitle.deviceSN), + _validate && _serviceReport.device?.id == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + AutoCompleteDeviceField( + hospitalId: widget.request.hospitalId, + initialValue: _serviceReport.device, + onPick: (id) { + _serviceReport.device.id = id; }, ), + const SizedBox(height: 8), ], ), ), - const SizedBox(width: 8,), - // visit date - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.visitDate), - _validate && _serviceReport.visitDate == null ? - ASubTitle(_subtitle.requiredWord,color: Colors.red,): - const SizedBox.shrink(), - Row( + const SizedBox(height: 8), + ASubTitle(_subtitle.assetType), + _validate && _serviceReport.assetType == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + const SizedBox( + height: 4, + ), + LoadingManager( + isLoading: _assetTypeProvider.isLoading, + isFailedLoading: _assetTypeProvider.statuses == null, + stateCode: _assetTypeProvider.stateCode, + onRefresh: () async { + _assetTypeProvider.reset(); + await _assetTypeProvider.getTypes(user: _userProvider.user, host: _settingProvider.host); + _serviceReport?.assetType = _assetTypeProvider.statuses?.firstWhere( + (element) => element.value == _callRequestForWorkOrder.assetType, + orElse: () => null, + ); + }, + child: ATextFormField( + initialValue: _serviceReport?.assetType?.name ?? "NULL", + textAlign: TextAlign.center, + enable: false, + style: Theme.of(context).textTheme.titleMedium, + ), + ), + // ServiceAssetTypeMenu( + // initialValue: _serviceReport.assetType, + // onSelect: (status) { + // _serviceReport.assetType = status; + // }, + // ), + const SizedBox( + height: 8, + ), + Row( + children: [ + // report status + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: ADatePicker( - date: _serviceReport.visitDate, - from: DateTime.now().subtract(const Duration(days: 365)), - to: DateTime.now().add(const Duration(days: 365)), - onDatePicker: (date){ - _serviceReport.visitDate = date; - setState(() {}); - }, - ), + // ASubTitle(_subtitle.reportStatus), + ASubTitle("Equipment Status"), + _validate && _serviceReport.equipmentStatus == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + const SizedBox( + height: 4, ), + // ServiceReportStatusMenu( + // report: _serviceReport, + // request: widget.request, + // onSelect: (status) { + // _serviceReport.status = status; + // }, + // ), + ServiceReportEquipmentStatusMenu( + report: _serviceReport, + request: widget.request, + onSelect: (status) { + _serviceReport.equipmentStatus = status; + }, + ) ], ), - ], - ), + ), + const SizedBox( + width: 8, + ), + // Provider.of(context).isLoading == null + // ? const SizedBox.shrink(): + // Call's last Situation + Consumer( + builder: (_, provider, __) { + if (provider.isLoading == null) return const SizedBox.shrink(); + return Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(_subtitle.callLastSituation), + _validate && _serviceReport.callLastSituation == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + const SizedBox(height: 4), + ServiceReportLastCallsMenu( + report: _serviceReport, + onSelect: (status) { + if (status?.value == 12 || _serviceReport.callLastSituation?.value == 12) { + _serviceReport.callLastSituation = status; + setState(() {}); + } else { + _serviceReport.callLastSituation = status; + setState(() {}); + } + }, + ), + ], + ), + ); + }, + ), + ], ), - - ], - ), - const SizedBox(height: 8,), - // device sn - Visibility( - visible: true,//widget.report.device == null, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.deviceSN), - _validate && _serviceReport.device?.id == null ? - ASubTitle(_subtitle.requiredWord,color: Colors.red,): - const SizedBox.shrink(), - AutoCompleteDeviceField( - hospitalId: widget.request.hospitalId, - initialValue: _serviceReport.device, - onPick: (id){ - _serviceReport.device.id = id; - }, - ), - const SizedBox(height: 8,), - ], - ), - ), - const SizedBox(height: 8,), - ASubTitle(_subtitle.serviceType), - _validate && _serviceReport.serviceType == null ? - ASubTitle(_subtitle.requiredWord,color: Colors.red,): - const SizedBox.shrink(), - const SizedBox(height: 4,), - ServiceStatusMenu( - initialValue: _serviceReport.serviceType, - onSelect: (status){ - _serviceReport.serviceType = status; - }, - ), - const SizedBox(height: 8,), - // Report status and Service Type - Row( - children: [ - // report status - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.reportStatus), - _validate && _serviceReport.status == null ? - ASubTitle(_subtitle.requiredWord,color: Colors.red,): - const SizedBox.shrink(), - const SizedBox(height: 4,), - ServiceReportStatusMenu( - report: _serviceReport, - onSelect: (status){ - _serviceReport.status = status; - }, - ), - ], - ), + const SizedBox( + height: 8, ), - const SizedBox(width: 8,), - Provider.of(context).isLoading == null - ? const SizedBox.shrink(): - // Call's last Situation - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - - ASubTitle(_subtitle.callLastSituation), - _validate && _serviceReport.callLastSituation == null ? - ASubTitle(_subtitle.requiredWord,color: Colors.red,): - const SizedBox.shrink(), - const SizedBox(height: 4,), - ServiceReportLastCallsMenu( - report: _serviceReport, - onSelect: (status){ - if(status?.id == 12 - || _serviceReport.callLastSituation?.id == 12){ - _serviceReport.callLastSituation = status; - setState(() {}); - } else { - _serviceReport.callLastSituation = status; - } + const ASubTitle("Return to Service"), + Row( + children: [ + Expanded( + child: ADatePicker( + date: _serviceReport.returnToService, + from: DateTime.now().subtract(const Duration(days: 365)), + to: DateTime.now().add(const Duration(days: 365)), + onDatePicker: (date) { + _serviceReport.returnToService = date; + setState(() {}); }, ), - ], - ), + ), + ], ), - ], - ), - const SizedBox(height: 8,), - // invoice number & code - _serviceReport.callLastSituation?.id != 12 ? const SizedBox.shrink(): - Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + if (_serviceReport?.callLastSituation?.value == 2) + Column( children: [ - ASubTitle(_subtitle.invoiceNumber), - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), ATextFormField( - initialValue: _serviceReport?.invoiceNumber, + initialValue: _serviceReport?.reviewComment, + hintText: "Vendor Name", textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - validator: (value) => - Validator.hasValue(value) - ? null : _subtitle.requiredWord, - textInputType: TextInputType.number, - onSaved: (value){ - _serviceReport.invoiceNumber = value; + style: Theme.of(context).textTheme.titleMedium, + textInputType: TextInputType.multiline, + onSaved: (value) { + _serviceReport.reviewComment = value; }, ), - ], - ), - ), - const SizedBox(width: 8,), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.invoiceCode), - const SizedBox(height: 4,), + const SizedBox( + height: 8, + ), ATextFormField( - initialValue: _serviceReport?.invoiceCode, + initialValue: _serviceReport?.reviewComment, + hintText: "Vendor Engineer", textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - validator: (value) => - Validator.hasValue(value) - ? null : _subtitle.requiredWord, - textInputType: TextInputType.text, - onSaved: (value){ - _serviceReport.invoiceCode = value; + style: Theme.of(context).textTheme.titleMedium, + textInputType: TextInputType.multiline, + onSaved: (value) { + _serviceReport.reviewComment = value; }, ), ], ), + if (_showCommentField) + const SizedBox( + height: 8, + ), + if (_showCommentField) + ATextFormField( + initialValue: _serviceReport?.reviewComment, + hintText: "Review Comment", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleMedium, + textInputType: TextInputType.multiline, + onSaved: (value) { + _serviceReport.reviewComment = value; + }, + ), + + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), ), - ], - ), + // const ASubTitle("Assign Employee"), + // const SizedBox( + // height: 8, + // ), + // _validate && _serviceReport.engineer == null + // ? ASubTitle( + // _subtitle.requiredWord, + // color: Colors.red, + // ) + // : const SizedBox.shrink(), + // const SizedBox( + // height: 4, + // ), + // EngineersMenu( + // initialValue: _serviceReport.engineer, + // onSelect: (engineer) { + // _serviceReport.engineer = engineer; + // }, + // ), + // const SizedBox( + // height: 8, + // ), + // Report status and Service Type + // Row( + // children: [ + // // report status + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // ASubTitle(_subtitle.reportStatus), + // _validate && _serviceReport.equipmentStatus == null + // ? ASubTitle( + // _subtitle.requiredWord, + // color: Colors.red, + // ) + // : const SizedBox.shrink(), + // const SizedBox( + // height: 4, + // ), + // ServiceReportStatusMenu( + // report: _serviceReport, + // request: widget.request, + // onSelect: (status) { + // _serviceReport.equipmentStatus = status; + // }, + // ), + // ], + // ), + // ), + // const SizedBox( + // width: 8, + // ), + // Consumer( + // builder: (_, provider, __) { + // if (provider.isLoading == null) return const SizedBox.shrink(); + // return Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // ASubTitle(_subtitle.callLastSituation), + // _validate && _serviceReport.callLastSituation == null + // ? ASubTitle( + // _subtitle.requiredWord, + // color: Colors.red, + // ) + // : const SizedBox.shrink(), + // const SizedBox( + // height: 4, + // ), + // ServiceReportLastCallsMenu( + // report: _serviceReport, + // onSelect: (status) { + // if (status?.value == 12 || _serviceReport.callLastSituation?.value == 12) { + // _serviceReport.callLastSituation = status; + // setState(() {}); + // } else { + // _serviceReport.callLastSituation = status; + // } + // }, + // ), + // ], + // ), + // ); + // }, + // ), + // ], + // ), + const SizedBox( + height: 8, + ), + // invoice number & code + _serviceReport.callLastSituation?.value != 12 + ? const SizedBox.shrink() + : Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(_subtitle.invoiceNumber), + const SizedBox( + height: 8, + ), + ATextFormField( + initialValue: _serviceReport?.invoiceNumber, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.subtitle1, + validator: (value) => Validator.hasValue(value) ? null : _subtitle.requiredWord, + textInputType: TextInputType.number, + onSaved: (value) { + _serviceReport.invoiceNumber = value; + }, + ), + ], + ), + ), + const SizedBox( + width: 8, + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(_subtitle.invoiceCode), + const SizedBox( + height: 4, + ), + ATextFormField( + initialValue: _serviceReport?.invoiceCode, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.subtitle1, + validator: (value) => Validator.hasValue(value) ? null : _subtitle.requiredWord, + textInputType: TextInputType.text, + onSaved: (value) { + _serviceReport.invoiceCode = value; + }, + ), + ], + ), + ), + ], + ), - const SizedBox(height: 8,), - Row( - children: [ - ASubTitle(_subtitle.faultDescription), - Expanded( - child: SizedBox( - height: 32 * AppStyle.getScaleFactor(context), - child: SpeechToTextButton( - controller: _faultController, - mini: true, + // const SizedBox(height: 8,), + // Row( + // children: [ + // ASubTitle(_subtitle.faultDescription), + // Expanded( + // child: SizedBox( + // height: 32 * AppStyle.getScaleFactor(context), + // child: SpeechToTextButton( + // controller: _faultController, + // mini: true, + // ), + // ), + // ), + // ], + // ), + // const SizedBox(height: 4,), + // ATextFormField( + // initialValue: _serviceReport?.faultDescriptionId, + // textAlign: TextAlign.center, + // controller: _faultController, + // style: Theme.of(context).textTheme.subtitle1, + // validator: (value) => + // Validator.hasValue(value) + // ? null : _subtitle.requiredWord, + // textInputType: TextInputType.multiline, + // onSaved: (value){ + // _serviceReport.faultDescriptionId = value; + // }, + // ), + // const SizedBox(height: 8,), + // Row( + // children: [ + // ASubTitle(_subtitle.workPreformed), + // Expanded( + // child: SizedBox( + // height: 32 * AppStyle.getScaleFactor(context), + // child: SpeechToTextButton( + // controller: _workPreformedController, + // mini: true, + // ), + // ), + // ), + // ], + // ), + // const SizedBox(height: 4,), + // ATextFormField( + // initialValue: _serviceReport?.workPreformed, + // textAlign: TextAlign.center, + // controller: _workPreformedController, + // style: Theme.of(context).textTheme.subtitle1, + // validator: (value) => + // Validator.hasValue(value) + // ? null : _subtitle.requiredWord, + // textInputType: TextInputType.multiline, + // onSaved: (value){ + // _serviceReport.workPreformed = value; + // }, + // ), + // const SizedBox(height: 8,), + const SizedBox(height: 8), + ASubTitle(_subtitle.workingHours), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: AppTimer( + timer: _serviceReport.timer, + enabled: false, + // onChange: (timer) async { + // _serviceReport.timer = timer; + // _serviceReport.workingHours = num.tryParse((((timer?.durationInSecond ?? 0) / 60) / 60)?.toStringAsFixed(2) ?? "0"); + // return true; + // }, + ), ), - ), + ], ), - ], - ), - const SizedBox(height: 4,), - ATextFormField( - initialValue: _serviceReport?.faultDescription, - textAlign: TextAlign.center, - controller: _faultController, - style: Theme.of(context).textTheme.subtitle1, - validator: (value) => - Validator.hasValue(value) - ? null : _subtitle.requiredWord, - textInputType: TextInputType.multiline, - onSaved: (value){ - _serviceReport.faultDescription = value; - }, - ), - const SizedBox(height: 8,), - Row( - children: [ - ASubTitle(_subtitle.workPreformed), - Expanded( - child: SizedBox( - height: 32 * AppStyle.getScaleFactor(context), - child: SpeechToTextButton( - controller: _workPreformedController, - mini: true, - ), + const SizedBox(height: 16), + if (_showCommentField) + const SizedBox( + height: 8, + ), + if (_showCommentField) + ATextFormField( + initialValue: _serviceReport?.reviewComment, + hintText: "Review Comment", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleMedium, + textInputType: TextInputType.multiline, + onSaved: (value) { + _serviceReport.reviewComment = value; + }, ), + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), + ), + const SizedBox(height: 8), + ASubTitle(_subtitle.faultDescription), + const SizedBox( + height: 4, + ), + ServiceReportFaultDescription( + requestId: widget.request?.id, + initialValue: _serviceReport.faultDescription, + onSelect: (status) { + print("faluttt:${status?.toJson()}"); + _serviceReport.faultDescription = status; + if (mounted) setState(() {}); + }, + ), + const SizedBox(height: 8), + const ASubTitle("Solutions"), + const SizedBox(height: 4), + ATextFormField( + initialValue: _serviceReport?.workPreformed, + textAlign: TextAlign.center, + enable: false, + hintText: _serviceReport.faultDescription?.workPerformed ?? "", + controller: _workPreformedController, + style: Theme.of(context).textTheme.subtitle1, + validator: (value) => Validator.hasValue(value) ? null : _subtitle.requiredWord, + textInputType: TextInputType.multiline, + onSaved: (value) { + // _serviceReport.workPreformed = value; + }, + ), + const SizedBox(height: 4), + ASubTitle("Failure Reason"), + const SizedBox( + height: 4, + ), + ServiceReportReasonsMenu( + initialValue: _serviceReport.reason, + onSelect: (status) { + _serviceReport.reason = status; + }, + ), + const SizedBox( + height: 8, + ), + ASubTitle(_subtitle.attachImage), + const SizedBox( + height: 4, + ), + MultiFilesPicker( + label: "", + files: _images, + ), + // AMiniOneImagePicker( + // //error: _validate && _serviceReport.image == null, + // image: _image, + // onPick: (image) { + // _image = image; + // _serviceReport.image = base64Encode(image.readAsBytesSync()); + // }, + // ), + const SizedBox( + height: 8, + ), + const SizedBox(height: 8), + ASubTitle(_subtitle.repairLocation), + const SizedBox(height: 4), + ServiceReportRepairLocation( + initialValue: _serviceReport.repairLocation, + onSelect: (status) { + _serviceReport.repairLocation = status; + }, + ), + const SizedBox(height: 16), + ASubTitle("Travel Expenses"), + const SizedBox( + height: 4, + ), + ATextFormField( + initialValue: _serviceReport?.travelingExpense?.toString(), + hintText: _subtitle.travelingExpense, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleMedium, + textInputType: TextInputType.number, + onSaved: (value) { + if (value != null && value.isEmpty) { + _serviceReport.travelingExpense = int.tryParse(_serviceReport?.travelingExpense?.toString() ?? "") ?? 0; + } else + _serviceReport.travelingExpense = int.tryParse(value) ?? 0; + }, ), - ], - ), - const SizedBox(height: 4,), - ATextFormField( - initialValue: _serviceReport?.workPreformed, - textAlign: TextAlign.center, - controller: _workPreformedController, - style: Theme.of(context).textTheme.subtitle1, - validator: (value) => - Validator.hasValue(value) - ? null : _subtitle.requiredWord, - textInputType: TextInputType.multiline, - onSaved: (value){ - _serviceReport.workPreformed = value; - }, - ), - const SizedBox(height: 8,), - const SizedBox(height: 8,), - Row( - children: [ - // reasons - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.reasons), - const SizedBox(height: 4,), - ServiceReportReasonsMenu( - initialValue: _serviceReport.reason, - onSelect: (status){ - _serviceReport.reason = status; - }, - ), - ], - ), + const SizedBox(height: 8), + ASubTitle(_subtitle.travelingHours), + const SizedBox(height: 4), + ATextFormField( + initialValue: _serviceReport?.travelingHours?.toString(), + textAlign: TextAlign.center, + hintText: "i.e 3, 3.5, 4", + style: Theme.of(context).textTheme.subtitle1, + // validator: (value) => + // Validator.isNumeric(value) + // ? null : _subtitle.requiredWord, + textInputType: TextInputType.number, + onSaved: (value) { + _serviceReport.travelingHours = double.tryParse(value) ?? 0.0; + }, ), - const SizedBox(width: 8,), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.attachImage), - AMiniOneImagePicker( - //error: _validate && _serviceReport.image == null, - image: _image, - onPick: (image){ - _image =image; - _serviceReport.image = base64Encode(image.readAsBytesSync()); - }, - ), - ], - ), + // Traveling Hours & Working Hours + // Row( + // children: [ + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // ASubTitle(_subtitle.workingHours), + // const SizedBox( + // height: 8, + // ), + // Row( + // children: [ + // Expanded( + // child: AppTimer( + // timer: _serviceReport.timer, + // onChange: (timer) async { + // _serviceReport.timer = timer; + // return true; + // }, + // ), + // ), + // ], + // ), + // // ATextFormField( + // // initialValue: _serviceReport?.workHours, + // // textAlign: TextAlign.center, + // // hintText: "i.e 3, 3.5, 4", + // // style: Theme.of(context).textTheme.subtitle1, + // // validator: (value) => + // // Validator.isNumeric(value) + // // ? null : _subtitle.requiredWord, + // // textInputType: TextInputType.number, + // // onSaved: (value){ + // // _serviceReport.workHours = value; + // // }, + // // ), + // ], + // ), + // ), + // // const SizedBox(width: 8,), + // // Expanded( + // // child: Column( + // // crossAxisAlignment: CrossAxisAlignment.start, + // // children: [ + // // ASubTitle(_subtitle.travelingHours), + // // const SizedBox(height: 4,), + // // ATextFormField( + // // initialValue: _serviceReport?.travelingHours, + // // textAlign: TextAlign.center, + // // hintText: "i.e 3, 3.5, 4", + // // style: Theme.of(context).textTheme.subtitle1, + // // validator: (value) => + // // Validator.isNumeric(value) + // // ? null : _subtitle.requiredWord, + // // textInputType: TextInputType.number, + // // onSaved: (value){ + // // _serviceReport.travelingHours = value; + // // }, + // // ), + // // ], + // // ), + // // ), + // ], + // ), + // const SizedBox( + // height: 8, + // ), + // Operating Hours and Job Sheet Number + // Row( + // children: [ + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // ASubTitle(_subtitle.operatingHours), + // const SizedBox(height: 4,), + // ATextFormField( + // initialValue: _serviceReport?.operatingHours, + // textAlign: TextAlign.center, + // hintText: "i.e 3, 3.5, 4", + // style: Theme.of(context).textTheme.subtitle1, + // validator: (value) => + // Validator.isNumeric(value) + // ? null : _subtitle.requiredWord, + // textInputType: TextInputType.number, + // onSaved: (value){ + // _serviceReport.operatingHours = value; + // }, + // ), + // ], + // ), + // ), + // const SizedBox(width: 8,), + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // ASubTitle(_subtitle.jobSheetNumber), + // const SizedBox(height: 4,), + // ATextFormField( + // initialValue: _serviceReport?.jobSheetNumber, + // textAlign: TextAlign.center, + // style: Theme.of(context).textTheme.subtitle1, + // textInputType: TextInputType.name, + // onSaved: (value){ + // _serviceReport.jobSheetNumber = value; + // }, + // ), + // ], + // ), + // ), + // ], + // ), + //const SizedBox(height: 8,), + + const SizedBox(height: 8), + const ASubTitle("Technical comment"), + const SizedBox(height: 4), + ATextFormField( + initialValue: _serviceReport?.comment, + hintText: "Technical Comment", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleMedium, + textInputType: TextInputType.multiline, + onSaved: (value) { + _serviceReport.comment = value; + }, ), - ], - ), - const SizedBox(height: 8,), - // Traveling Hours & Working Hours - Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.workingHours), - const SizedBox(height: 8,), - AppTimer( - timer: _serviceReport.timer, - onChange: (timer) async{ - _serviceReport.timer = timer; - return true; - }, - ), - // ATextFormField( - // initialValue: _serviceReport?.workHours, - // textAlign: TextAlign.center, - // hintText: "i.e 3, 3.5, 4", - // style: Theme.of(context).textTheme.subtitle1, - // validator: (value) => - // Validator.isNumeric(value) - // ? null : _subtitle.requiredWord, - // textInputType: TextInputType.number, - // onSaved: (value){ - // _serviceReport.workHours = value; - // }, - // ), - ], - ), + const SizedBox(height: 8), + const ASubTitle("Nurse Signature"), + ESignature( + oldSignature: _serviceReport.signatureNurse, + newSignature: _serviceReport.localNurseSignature, + onSaved: (signature) { + if (signature == null || signature.isEmpty) { + return; + } + _serviceReport.localNurseSignature = signature; + _serviceReport.signatureNurse = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + }, ), - const SizedBox(width: 8,), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.travelingHours), - const SizedBox(height: 4,), - ATextFormField( - initialValue: _serviceReport?.travelingHours, - textAlign: TextAlign.center, - hintText: "i.e 3, 3.5, 4", - style: Theme.of(context).textTheme.subtitle1, - validator: (value) => - Validator.isNumeric(value) - ? null : _subtitle.requiredWord, - textInputType: TextInputType.number, - onSaved: (value){ - _serviceReport.travelingHours = value; - }, - ), - ], - ), + const SizedBox( + height: 8, ), - ], - ), - const SizedBox(height: 8,), - // Operating Hours and Job Sheet Number - Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.operatingHours), - const SizedBox(height: 4,), - ATextFormField( - initialValue: _serviceReport?.operatingHours, - textAlign: TextAlign.center, - hintText: "i.e 3, 3.5, 4", - style: Theme.of(context).textTheme.subtitle1, - validator: (value) => - Validator.isNumeric(value) - ? null : _subtitle.requiredWord, - textInputType: TextInputType.number, - onSaved: (value){ - _serviceReport.operatingHours = value; - }, - ), - ], - ), + const ASubTitle("Engineer Signature"), + ESignature( + oldSignature: _serviceReport.signatureEngineer, + newSignature: _serviceReport.localNurseSignature, + onSaved: (signature) { + if (signature == null || signature.isEmpty) { + return; + } + _serviceReport.localNurseSignature = signature; + _serviceReport.signatureEngineer = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + }, ), - const SizedBox(width: 8,), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(_subtitle.jobSheetNumber), - const SizedBox(height: 4,), - ATextFormField( - initialValue: _serviceReport?.jobSheetNumber, - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - textInputType: TextInputType.name, - onSaved: (value){ - _serviceReport.jobSheetNumber = value; - }, - ), - ], - ), + const SizedBox( + height: 8, ), + // Part Number and Quantity ], ), - const SizedBox(height: 8,), - // Part Number and Quantity + ), + ], + ), + ASubTitle("Spare Parts"), + Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + margin: const EdgeInsets.symmetric(vertical: 16), + decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [ + BoxShadow( + color: AColors.grey, + offset: Offset(0, -1), + ) + ]), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ Row( children: [ Expanded( @@ -550,13 +1000,18 @@ class _EditServiceReportState extends State with TickerProvid child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - ASubTitle(_subtitle.partNumber), - _validate && _serviceReport.parts == null ? - ASubTitle(_subtitle.requiredWord,color: Colors.red,): - const SizedBox.shrink(), - const SizedBox(height: 4,), + ASubTitle(_subtitle.partNumberName), + _validate && _serviceReport.parts == null + ? ASubTitle( + _subtitle.requiredWord, + color: Colors.red, + ) + : const SizedBox.shrink(), + const SizedBox( + height: 4, + ), AutoCompletePartsField( - onPick: (part){ + onPick: (part) { _serviceReport.parts.add(part); setState(() {}); }, @@ -564,85 +1019,75 @@ class _EditServiceReportState extends State with TickerProvid ], ), ), - ], ), - SizedBox(height: 8*AppStyle.getScaleFactor(context),), + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), + ), Row( children: [ - Expanded(flex:3,child: Text(_subtitle.number)), - Expanded(flex: 1,child: Text(_subtitle.quantity)), + Expanded(flex: 3, child: Text(_subtitle.number)), + Expanded(flex: 1, child: Text(_subtitle.quantity)), ], ), Column( - children: List.generate( - _serviceReport.parts.length, - (index) { - Part _part = _serviceReport.parts[index]; - return PartItem( - part: _part, - onDelete: (part){ - _serviceReport.parts.remove(part); - setState(() {}); - }, - ); - } - ), + children: List.generate(_serviceReport.parts.length, (index) { + Part _part = _serviceReport.parts[index]; + return PartItem( + part: _part, + onDelete: (part) { + _serviceReport.parts.remove(part); + setState(() {}); + }, + ); + }), + ), + const SizedBox( + height: 16, ), - - const SizedBox(height: 16,), - ], ), ), - Padding( - padding: const EdgeInsets.all(16.0), - child: AButton( - text: _subtitle.update, - onPressed: () async { - _validate = true; - if(!_formKey.currentState.validate()){ - setState(() {}); - return; - } - if(!_serviceReport.validate()) { - setState(() {}); - return; - } - _formKey.currentState.save(); + AButton( + text: _subtitle.update, + onPressed: () async { + if (_serviceReport?.workingHours == null) { + await Fluttertoast.showToast(msg: "Working Hours Timer Isn't Started"); + return; + } + _validate = true; + // if (!_formKey.currentState.validate()) { + // setState(() {}); + // return; + // } + // print("jere124"); + // if (!_serviceReport.validate()) { + // setState(() {}); + // return; + // } + // print("jere14"); + _formKey.currentState.save(); - _isLoading =true; - setState(() {}); - - int status = await _serviceRequestsProvider.updateServiceReport( - user: _userProvider.user, - host: _settingProvider.host, - report: _serviceReport, - request: widget.request + _isLoading = true; + setState(() {}); + _serviceReport.image = _images.map((e) => base64Encode(e.readAsBytesSync())).toList(); + int status = await _serviceRequestsProvider.updateServiceReport(user: _userProvider.user, host: _settingProvider.host, report: _serviceReport, request: widget.request); + _isLoading = false; + setState(() {}); + if (status >= 200 && status < 300) { + Fluttertoast.showToast( + msg: _subtitle.requestCompleteSuccessfully, ); - _isLoading =false; - setState(() {}); - if(status >= 200 && status < 300){ - Fluttertoast.showToast( - msg: _subtitle.requestCompleteSuccessfully, - ); - Navigator.of(context).pop(); - Navigator.of(context).pop(); - }else{ - String errorMessage = HttpStatusManger.getStatusMessage( - status: status, subtitle: _subtitle); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - errorMessage - ), - ) - ); - } - }, - ), + Navigator.of(context).pop(); + Navigator.of(context).pop(); + } else { + String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(errorMessage), + )); + } + }, ), - const SizedBox(height: 300,) ], ), const ABackButton(), diff --git a/lib/views/pages/user/requests/report/future_service_report.dart b/lib/views/pages/user/requests/report/future_service_report.dart index 5ee16ea2..258a857b 100644 --- a/lib/views/pages/user/requests/report/future_service_report.dart +++ b/lib/views/pages/user/requests/report/future_service_report.dart @@ -5,51 +5,54 @@ import 'package:test_sa/controllers/providers/api/service_requests_provider.dart import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/service_report.dart'; +import 'package:test_sa/models/service_request/search_work_order.dart'; import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; import 'package:test_sa/views/widgets/loaders/failed_loading.dart'; import 'edit_service_report.dart'; + class FutureServiceReport extends StatefulWidget { final ServiceRequest request; + final SearchWorkOrder workOrder; - const FutureServiceReport({Key key, this.request}) : super(key: key); + const FutureServiceReport({Key key, this.request, this.workOrder}) : super(key: key); @override _FutureServiceReportState createState() => _FutureServiceReportState(); } class _FutureServiceReportState extends State { - UserProvider _userProvider; SettingProvider _settingProvider; + @override Widget build(BuildContext context) { _userProvider = Provider.of(context); _settingProvider = Provider.of(context); - Subtitle _subtitle = AppLocalization.of(context).subtitle; + Subtitle subtitle = AppLocalization.of(context).subtitle; + ServiceRequestsProvider().getSingleServiceReport(reportId: widget.workOrder.id, user: _userProvider.user, host: _settingProvider.host, subtitle: subtitle); return Scaffold( body: FutureBuilder( - future: ServiceRequestsProvider().getSingleServiceReport( - reportId: widget.request.reportID, - user: _userProvider.user, - host: _settingProvider.host, - subtitle: _subtitle - ), - builder: (BuildContext context, AsyncSnapshot snapshot){ - if(snapshot.hasError) + future: ServiceRequestsProvider().getSingleServiceReport(reportId: widget.workOrder.id, user: _userProvider.user, host: _settingProvider.host, subtitle: subtitle), + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.hasError) { return FailedLoading( message: snapshot.error.toString(), - onReload: (){setState(() {});}, + onReload: () { + setState(() {}); + }, ); - if(snapshot.hasData){ + } + if (snapshot.connectionState == ConnectionState.done) { + print("object"); return EditServiceReport( report: snapshot.data, request: widget.request, ); } - return Center(child: ALoading()); + return const Center(child: ALoading()); }, ), ); diff --git a/lib/views/pages/user/requests/request_details.dart b/lib/views/pages/user/requests/request_details.dart index 2ada571e..a794e5f5 100644 --- a/lib/views/pages/user/requests/request_details.dart +++ b/lib/views/pages/user/requests/request_details.dart @@ -1,42 +1,43 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/http_status_manger/http_status_manger.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; +import 'package:test_sa/views/pages/user/requests/create_request.dart'; import 'package:test_sa/views/pages/user/requests/report/create_service_report.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; import 'package:test_sa/views/widgets/buttons/app_icon_button.dart'; -import 'package:test_sa/views/widgets/dialogs/dialog.dart'; import 'package:test_sa/views/widgets/images/images_list.dart'; import 'package:test_sa/views/widgets/loaders/image_loader.dart'; import 'package:test_sa/views/widgets/requests/info_row.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart'; -import 'package:test_sa/views/widgets/requests/service_request_update_dialog.dart'; import 'package:test_sa/views/widgets/sound/sound_player.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; -import '../report_issues_page.dart'; +import '../../../../models/service_request/search_work_order.dart'; import 'report/future_service_report.dart'; + class RequestDetailsPage extends StatelessWidget { - static final String id = "/call-details"; + static const String id = "/call-details"; final ServiceRequest serviceRequest; const RequestDetailsPage({Key key, this.serviceRequest}) : super(key: key); + @override Widget build(BuildContext context) { Subtitle _subtitle = AppLocalization.of(context).subtitle; UserProvider _userProvider = Provider.of(context); SettingProvider _settingProvider = Provider.of(context); + List workOrders = []; ServiceRequestsProvider _serviceRequestsProvider = Provider.of(context); return DefaultTabController( length: 2, @@ -45,8 +46,8 @@ class RequestDetailsPage extends StatelessWidget { child: Column( children: [ Container( - color:AColors.primaryColor, - padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), + color: AColors.primaryColor, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), child: Row( children: [ ABackButton(), @@ -54,131 +55,138 @@ class RequestDetailsPage extends StatelessWidget { child: Center( child: Text( _subtitle.details, - style: Theme.of(context).textTheme.headline6.copyWith( - color: AColors.white, - fontStyle: FontStyle.italic - ), + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), ), ), ), - Visibility( - visible: _userProvider.user.type == UsersTypes.normal_user, - replacement: AIconButton( - iconData: Icons.edit, - color: AColors.white, - buttonSize: 42, - backgroundColor: AColors.green, - onPressed: () async { - showModalBottomSheet( - context: context, - builder: (context){ - return ServiceRequestsUpdateDialog(request: serviceRequest,); - }); - // DateTime picked = await showDatePicker( - // context: context, - // initialDate: DateTime.now(), - // firstDate: DateTime.now(), - // lastDate: DateTime.now().add(Duration(days: 182)) - // ); - // if(picked == null){return;} - // showDialog( - // context: context, - // barrierDismissible: false, - // builder: (BuildContext context) { - // return CupertinoAlertDialog( - // title: Text(_subtitle.updatingDots), - // content: Center(child: CircularProgressIndicator()), - // ); - // }, - // ); - // int status = await _serviceRequestsProvider.updateDate( - // user: _userProvider.user, - // host: _settingProvider.host, - // request: serviceRequest, - // newDate: picked.toString().split(" ").first - // ); - // Navigator.of(context).pop(); - // Fluttertoast.showToast( - // msg: HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle), - // ); - }, - ), - child: AIconButton( - iconData: Icons.warning_amber_rounded, - color: AColors.white, - buttonSize: 42, - backgroundColor: AColors.deepOrange, - onPressed: (){ - Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => ReportIssuesPage(serviceRequest: serviceRequest,) - ) - ); - }, - ), - ), - SizedBox(width: 16,) + _userProvider.user.type == UsersTypes.normal_user + ? + // AIconButton( + // iconData: Icons.warning_amber_rounded, + // color: AColors.white, + // buttonSize: 42, + // backgroundColor: AColors.deepOrange, + // onPressed: (){ + // Navigator.of(context).push( + // MaterialPageRoute( + // builder: (_) => ReportIssuesPage(serviceRequest: serviceRequest,) + // ) + // ); + // }, + // ) + const SizedBox( + width: 48, + ) + : AIconButton( + iconData: Icons.edit, + color: AColors.white, + buttonSize: 42, + backgroundColor: AColors.green, + onPressed: () async { + Navigator.of(context).push( + MaterialPageRoute(builder: (_) => CreateRequestPage(serviceRequest: serviceRequest)), + ); + // showModalBottomSheet( + // context: context, + // builder: (context) { + // return ServiceRequestsUpdateDialog( + // request: serviceRequest, + // ); + // }); + // DateTime picked = await showDatePicker( + // context: context, + // initialDate: DateTime.now(), + // firstDate: DateTime.now(), + // lastDate: DateTime.now().add(Duration(days: 182)) + // ); + // if(picked == null){return;} + // showDialog( + // context: context, + // barrierDismissible: false, + // builder: (BuildContext context) { + // return CupertinoAlertDialog( + // title: Text(_subtitle.updatingDots), + // content: Center(child: CircularProgressIndicator()), + // ); + // }, + // ); + // int status = await _serviceRequestsProvider.updateDate( + // user: _userProvider.user, + // host: _settingProvider.host, + // request: serviceRequest, + // newDate: picked.toString().split(" ").first + // ); + // Navigator.of(context).pop(); + // Fluttertoast.showToast( + // msg: HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle), + // ); + }, + ), + SizedBox( + width: 16, + ) ], ), ), - - serviceRequest.devicePhotos.isEmpty ? SizedBox.shrink(): - Column( - children: [ - SizedBox(height: 8,), - MaterialButton( - padding: EdgeInsets.zero, - onPressed: (){ - Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => Scaffold( - body: InteractiveViewer( - child: Center( - child: ImageLoader( - url: serviceRequest.devicePhotos.first, - boxFit: BoxFit.contain, - ), - ), - ), - ) - ) - ); - }, - child: SizedBox( - height: 140 * AppStyle.getScaleFactor(context), - width: MediaQuery.of(context).size.width, - child: ImageLoader( - url: serviceRequest.devicePhotos.first, - boxFit: BoxFit.cover, - ), - ), - ), - SizedBox(height: 8,), - SizedBox( - height: 60* AppStyle.getScaleFactor(context), - child: ImagesList( - images: serviceRequest.devicePhotos, + serviceRequest.devicePhotos.isEmpty + ? SizedBox.shrink() + : Column( + children: [ + SizedBox( + height: 8, + ), + MaterialButton( + padding: EdgeInsets.zero, + onPressed: () { + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => Scaffold( + body: InteractiveViewer( + child: Center( + child: ImageLoader( + url: serviceRequest.devicePhotos.first, + boxFit: BoxFit.contain, + ), + ), + ), + ))); + }, + child: SizedBox( + height: 140 * AppStyle.getScaleFactor(context), + width: MediaQuery.of(context).size.width, + child: ImageLoader( + url: serviceRequest.devicePhotos.first, + boxFit: BoxFit.cover, + ), + ), + ), + SizedBox(height: 8), + SizedBox( + height: 60 * AppStyle.getScaleFactor(context), + child: ImagesList( + images: serviceRequest.devicePhotos, + ), + ), + ], ), - ), - ], - ), - - TabBar( - labelColor: AColors.primaryColor, - tabs: [ - Tab(text: _subtitle.general,), - Tab(text: _subtitle.serviceRequestInformation,), + TabBar(labelColor: AColors.primaryColor, tabs: [ + Tab( + text: _subtitle.general, + ), + Tab( + text: _subtitle.serviceRequestInformation, + ), ]), - SizedBox(height: 8,), + SizedBox( + height: 8, + ), Expanded( child: TabBarView( - children: [ ListView( padding: EdgeInsets.symmetric(horizontal: 16), children: [ RequestInfoRow( - title: _subtitle.code, + title: _subtitle.callId, info: serviceRequest.requestCode, ), RequestInfoRow( @@ -186,12 +194,12 @@ class RequestDetailsPage extends StatelessWidget { info: serviceRequest.deviceNumber, ), RequestInfoRow( - title: _subtitle.deviceSN, - info: serviceRequest.deviceSerialNumber, + title: _subtitle.assetName, + info: serviceRequest.deviceEnName, ), RequestInfoRow( title: _subtitle.deviceModel, - info : serviceRequest.deviceModel, + info: serviceRequest.deviceModel, ), RequestInfoRow( title: _subtitle.engineerName, @@ -205,11 +213,12 @@ class RequestDetailsPage extends StatelessWidget { title: _subtitle.date, info: serviceRequest.date, ), - serviceRequest.nextVisitDate == null ? SizedBox.shrink() : - RequestInfoRow( - title: _subtitle.nextVisitDate, - info: DateFormat('EE dd/MM/yyyy').format(serviceRequest.nextVisitDate), - ), + serviceRequest.nextVisitDate == null + ? SizedBox.shrink() + : RequestInfoRow( + title: _subtitle.nextVisitDate, + info: DateFormat('EE dd/MM/yyyy').format(serviceRequest.nextVisitDate), + ), Row( children: [ Expanded( @@ -219,12 +228,12 @@ class RequestDetailsPage extends StatelessWidget { textScaleFactor: AppStyle.getScaleFactor(context), ), ), - StatusLabel(label: serviceRequest.statusLabel, - color: AColors.getRequestStatusColor(serviceRequest.statusValue) - ), + StatusLabel(label: serviceRequest.statusLabel, color: AColors.getRequestStatusColor(serviceRequest.statusValue)), ], ), - Divider(color: Theme.of(context).primaryColor,), + Divider( + color: Theme.of(context).primaryColor, + ), RequestInfoRow( title: _subtitle.hospital, info: serviceRequest.hospitalName, @@ -237,116 +246,192 @@ class RequestDetailsPage extends StatelessWidget { // title: _subtitle.deviceArName, // content: serviceRequest.deviceArName, // ), - RequestInfoRow( - title: _subtitle.deviceEnName, - content: serviceRequest.deviceEnName, - ), + // RequestInfoRow( + // title: _subtitle.deviceName, + // content: serviceRequest.deviceEnName, + // ), RequestInfoRow( title: _subtitle.maintenanceIssue, - content: serviceRequest.maintenanceIssue, - ), - if(serviceRequest.audio?.isNotEmpty == true) - ASoundPlayer( - audio: serviceRequest.audio, + content: serviceRequest.callComments, ), - Center( - child: Padding( - padding: EdgeInsets.all(32), - child: AButton( - text: _subtitle.duplicateRequest, - onPressed: () async { - bool result = await showDialog( - context: context, - builder: (_) => AAlertDialog( - title: _subtitle.duplicateAlert, - content: _subtitle.duplicateAlertMessage, - ) - ); - if(result == true){ - showDialog( - context: context, - builder: (context){ - return Center(child: CircularProgressIndicator()); - } - ); - int status = await _serviceRequestsProvider.createDuplicatedReport( - host: _settingProvider.host, - user: _userProvider.user, - request: serviceRequest - ); - Navigator.of(context).pop(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle) - ) - ) - ); - } - }, - ), + if (serviceRequest.audio?.isNotEmpty == true) + ASoundPlayer( + audio: serviceRequest.audio, ), - ) + // + // Center( + // child: Padding( + // padding: EdgeInsets.all(32), + // child: AButton( + // text: _subtitle.duplicateRequest, + // onPressed: () async { + // bool result = await showDialog( + // context: context, + // builder: (_) => AAlertDialog( + // title: _subtitle.duplicateAlert, + // content: _subtitle.duplicateAlertMessage, + // ) + // ); + // if(result == true){ + // showDialog( + // context: context, + // builder: (context){ + // return Center(child: CircularProgressIndicator()); + // } + // ); + // int status = await _serviceRequestsProvider.createDuplicatedReport( + // host: _settingProvider.host, + // user: _userProvider.user, + // request: serviceRequest + // ); + // Navigator.of(context).pop(); + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar( + // content: Text( + // HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle) + // ) + // ) + // ); + // } + // }, + // ), + // ), + // ) ], ), - serviceRequest.viewReport ? - ListView( - padding: EdgeInsets.symmetric(horizontal: 16), - children: [ - RequestInfoRow( - title: _subtitle.faultDescription, - content: serviceRequest.faultDescription, - ), - RequestInfoRow( - title: _subtitle.workPerformed, - content: serviceRequest.workPerformed, - ), - RequestInfoRow( - title: _subtitle.visitDate, - info: serviceRequest.visitDate, - ), - RequestInfoRow( - title: _subtitle.jobSheetNumber, - info: serviceRequest.jobSheetNumber, - ), - _userProvider.user.type == UsersTypes.engineer ? - Padding( - padding: EdgeInsets.all(32), - child: AButton( - text: _subtitle.editServiceReport, - onPressed: (){ - Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => FutureServiceReport( - request: serviceRequest, - ) + // workOrders.isEmpty ? + FutureBuilder( + future: _serviceRequestsProvider.searchWorkOrders(callId: serviceRequest.requestCode), + builder: (context, snap) { + workOrders = snap.data as List; + if (snap.connectionState == ConnectionState.waiting) return Center(child: CircularProgressIndicator()); + if (snap.connectionState == ConnectionState.done && (snap.data?.length ?? 0) != 0) { + return SingleChildScrollView( + child: Column( + children: [ + ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.all(21), + itemCount: workOrders.length, + separatorBuilder: (czt, index) => 21.height, + itemBuilder: (context, index) { + Color itemColor = index % 2 == 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; + Color onItemColor = index % 2 != 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; + + return ElevatedButton( + style: ElevatedButton.styleFrom( + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8), + primary: itemColor.withOpacity(.7), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), + ), + ), + //padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8), + onPressed: () { + // onPressed(request); + }, + child: Column( + children: [ + RequestInfoRow( + title: _subtitle.callId, + content: serviceRequest.requestCode, + ), + RequestInfoRow( + title: _subtitle.orderWorkNumber, + info: workOrders[index].workOrderNo.toString(), + ), + RequestInfoRow( + title: _subtitle.visitDate, + info: workOrders[index].visitDate, + ), + RequestInfoRow(title: _subtitle.assignedEmployee, info: workOrders[index].assignedEmployee?.name ?? ""), + RequestInfoRow( + title: _subtitle.assetSN, + info: workOrders[index].callRequest.asset.assetSerialNo, + ), + RequestInfoRow( + title: _subtitle.assetName, + info: workOrders[index].callRequest.asset.modelDefinition.assetName, + ), + RequestInfoRow( + title: _subtitle.assetNumber, + info: workOrders[index].callRequest.asset.assetNumber, + ), + RequestInfoRow( + title: _subtitle.model, + info: workOrders[index].callRequest.asset.modelDefinition.modelName, + ), + RequestInfoRow( + title: _subtitle.site, + info: workOrders[index].callRequest.asset.site.custName, + ), + RequestInfoRow( + title: "Call last Situation", + info: workOrders[index].currentSituation.name ?? '', + ), + _userProvider.user.type == UsersTypes.engineer && workOrders[index].workOrderNo != null + ? Padding( + padding: EdgeInsets.all(32), + child: AButton( + text: _subtitle.editServiceReport, + onPressed: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => FutureServiceReport( + request: serviceRequest, + workOrder: workOrders[index], + )), + ); + }, + ), + ) + : SizedBox.shrink(), + ], + ), + ); + }, + ), + if (_userProvider.user.type == UsersTypes.engineer) + Center( + child: Padding( + padding: const EdgeInsets.all(32), + child: AButton( + text: "Create Work Order", + onPressed: () { + Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest))); + }, + ), + ), + ), + ], + ), + ); + } else { + return Column( + children: [ + Expanded( + child: Center( + child: ASubTitle(_subtitle.dataNotFound), ), - ); - }, - ), - ): SizedBox.shrink(), - ], - ): - _userProvider.user.type == UsersTypes.engineer ? - Center( - child: Padding( - padding: EdgeInsets.all(32), - child: AButton( - text: "Create Report", - onPressed: (){ - Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => CreateServiceReport( - request: serviceRequest, - ) ), - ); - }, - ), - ), - ): Center(child: ASubTitle(_subtitle.noDateFound),), - - + if (_userProvider.user.type == UsersTypes.engineer) + Center( + child: Padding( + padding: const EdgeInsets.all(32), + child: AButton( + text: "Create Work Order", + onPressed: () { + Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest))); + }, + ), + ), + ), + ], + ); + } + }, + ), ], ), ), diff --git a/lib/views/pages/user/requests/requests_page.dart b/lib/views/pages/user/requests/requests_page.dart index e535d03b..65f00cdb 100644 --- a/lib/views/pages/user/requests/requests_page.dart +++ b/lib/views/pages/user/requests/requests_page.dart @@ -12,26 +12,28 @@ import 'package:test_sa/views/widgets/buttons/app_icon_button.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/requests/service_request_list.dart'; import 'package:test_sa/views/widgets/search/service_request_search_bar.dart'; + class ServiceRequestsPage extends StatefulWidget { static final String id = "/service-requests"; + @override _ServiceRequestsPageState createState() => _ServiceRequestsPageState(); } -class _ServiceRequestsPageState extends State - with TickerProviderStateMixin{ +class _ServiceRequestsPageState extends State with TickerProviderStateMixin { ServiceRequestsProvider _serviceRequestsProvider; UserProvider _userProvider; SettingProvider _settingProvider; bool _expandedSearch = false; bool _firstTime = true; + @override Widget build(BuildContext context) { _serviceRequestsProvider = Provider.of(context); _userProvider = Provider.of(context); _settingProvider = Provider.of(context); Subtitle _subtitle = AppLocalization.of(context).subtitle; - if(_firstTime){ + if (_firstTime) { _serviceRequestsProvider.reset(); _firstTime = false; } @@ -44,19 +46,15 @@ class _ServiceRequestsPageState extends State stateCode: _serviceRequestsProvider.stateCode, onRefresh: () async { _serviceRequestsProvider.reset(); - await _serviceRequestsProvider.getRequests( - user: _userProvider.user, - host: _settingProvider.host, - hospitalId: _userProvider.user.hospital.id, - ); + await _serviceRequestsProvider.getRequests(hospitalId: _userProvider.user.clientId); }, child: Stack( children: [ Column( children: [ Container( - color:AColors.primaryColor, - padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), + color: AColors.primaryColor, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), child: Column( children: [ Row( @@ -66,10 +64,7 @@ class _ServiceRequestsPageState extends State child: Center( child: Text( _subtitle.serviceRequests, - style: Theme.of(context).textTheme.headline6.copyWith( - color: AColors.white, - fontStyle: FontStyle.italic - ), + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), ), ), ), @@ -83,22 +78,23 @@ class _ServiceRequestsPageState extends State ServiceRequestSearch _temp = await showModalBottomSheet( context: context, isScrollControlled: true, - builder: (context){ + builder: (context) { return ServiceRequestsSearchDialog( initialSearchValue: _serviceRequestsProvider.search, ); }); - if(_temp != null){ + if (_temp != null) { _serviceRequestsProvider.search = _temp; _serviceRequestsProvider.reset(); setState(() {}); } }, ), - SizedBox(width: 16,) + SizedBox( + width: 16, + ) ], ), - ], ), ), @@ -106,18 +102,13 @@ class _ServiceRequestsPageState extends State child: ServiceRequestsList( nextPage: _serviceRequestsProvider.nextPage, onLazyLoad: () async { - await _serviceRequestsProvider.getRequests( - user: _userProvider.user, - host: _settingProvider.host, - hospitalId: _userProvider.user.hospital.id, - ); + await _serviceRequestsProvider.getRequests(hospitalId: _userProvider.user.clientId); }, requests: _serviceRequestsProvider.serviceRequests, ), ), ], ), - ], ), ), diff --git a/lib/views/pages/user/visits/pantry/edit_pentry.dart b/lib/views/pages/user/visits/pantry/edit_pentry.dart index 7c9201b1..c576702a 100644 --- a/lib/views/pages/user/visits/pantry/edit_pentry.dart +++ b/lib/views/pages/user/visits/pantry/edit_pentry.dart @@ -1,31 +1,35 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/http_status_manger/http_status_manger.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/regular_visits_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/models/pantry/calibration_tools.dart'; import 'package:test_sa/models/pantry/pentry.dart'; +import 'package:test_sa/models/pantry/pm_kit.dart'; +import 'package:test_sa/models/pantry/ppm_check_list.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/models/visits/visit.dart'; import 'package:test_sa/views/widgets/buttons/app_small_button.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/pentry/pentry_calibration_tool_form.dart'; -import 'package:test_sa/views/widgets/pentry/pentry_info_form.dart'; import 'package:test_sa/views/widgets/pentry/pentry_pm_kit_form.dart'; import 'package:test_sa/views/widgets/pentry/pentry_ppm_check_list_form.dart'; +import '../../../../widgets/pentry/pentry_info_form.dart'; + class EditPentry extends StatefulWidget { final Pentry pentry; final Visit visit; - const EditPentry({Key key,this.pentry, this.visit}) : super(key: key); + + const EditPentry({Key key, this.pentry, this.visit}) : super(key: key); @override State createState() => _EditPentryState(); } -class _EditPentryState extends State with SingleTickerProviderStateMixin{ +class _EditPentryState extends State with SingleTickerProviderStateMixin { bool _isLoading = false; bool _validate = false; Subtitle _subtitle; @@ -36,42 +40,42 @@ class _EditPentryState extends State with SingleTickerProviderStateM final GlobalKey _scaffoldKey = GlobalKey(); TabController _tabController; + _onSubmit() async { _validate = true; - if(!_pentry.validate()) { - setState(() { }); + if (!(await _pentry.validate())) { + setState(() {}); return; } _isLoading = true; setState(() {}); - int status = await _regularVisitsProvider.updatePentry( - user: _userProvider.user, - host: _settingProvider.host, - pentry: _pentry, - visit: widget.visit - ); - _isLoading =false; + int status = await _regularVisitsProvider.updatePentry(user: _userProvider.user, host: _settingProvider.host, pentry: _pentry, visit: widget.visit); + _isLoading = false; setState(() {}); - if(status >= 200 && status < 300){ + if (status >= 200 && status < 300) { Fluttertoast.showToast( msg: _subtitle.requestCompleteSuccessfully, ); - // Navigator.of(context).pop(); - }else{ - String errorMessage = HttpStatusManger.getStatusMessage( - status: status, subtitle: _subtitle); - Fluttertoast.showToast( - msg: errorMessage, - ); + Navigator.of(context).pop(); + Navigator.of(context).pop(); + } else { + // String errorMessage = HttpStatusManger.getStatusMessage( + // status: status, subtitle: _subtitle); + // Fluttertoast.showToast( + // msg: errorMessage, + // ); } } @override void initState() { - _pentry = widget.pentry; + _pentry = widget.pentry.copyWith(); + if (_pentry.pmKits.isEmpty) _pentry.pmKits.add(PMKit()); + if (_pentry.calibrationTools.isEmpty) _pentry.calibrationTools.add(CalibrationTool()); + if (_pentry.ppmCheckLists.isEmpty) _pentry.ppmCheckLists.add(PPMCheckList()); _tabController = TabController(length: 4, vsync: this); super.initState(); } @@ -92,96 +96,106 @@ class _EditPentryState extends State with SingleTickerProviderStateM key: _scaffoldKey, body: SafeArea( child: LoadingManager( - isLoading: _isLoading, - isFailedLoading: false, - stateCode: 200, - onRefresh: () async {}, - child: Column( - children: [ - Material( - color: Theme.of(context).colorScheme.primary, - child: Padding( - padding: const EdgeInsets.all(2.0), - child: TabBar( - controller: _tabController, - isScrollable: true, - onTap: (index){ - setState(() {}); - }, - tabs: const [ - Tab(text: "PPM Check List",), - Tab(text: "Calibration Tools",), - Tab(text: "PK Kits",), - Tab(text: "Pentry",), - ]), - ), - ), - Expanded( - child: Stack( - children: [ - TabBarView( - physics: const NeverScrollableScrollPhysics(), - controller: _tabController, - children: [ - PentryPPMCheckListForm( - models: _pentry.ppmCheckLists, - enableValidate: _validate, - ), - PentryCalibrationToolForm( - models: _pentry.calibrationTools, - enableValidate: _validate, - ), - PentryPMKitForm( - models: _pentry.pmKits, - enableValidate: _validate, - ), - PentryInfoForm( - model: _pentry, - enableValidate: _validate, - ) + isLoading: _isLoading, + isFailedLoading: false, + stateCode: 200, + onRefresh: () async {}, + child: Column( + children: [ + Material( + color: Theme.of(context).colorScheme.primary, + child: Padding( + padding: const EdgeInsets.all(2.0), + child: TabBar( + controller: _tabController, + isScrollable: true, + onTap: (index) { + setState(() {}); + }, + tabs: const [ + Tab( + text: "PPM Check List", + ), + Tab( + text: "Calibration Tools", + ), + Tab( + text: "PM Kits", + ), + Tab( + text: "PM Entry", + ), + ], + ), + ), + ), + Expanded( + child: Stack( + children: [ + TabBarView( + physics: const NeverScrollableScrollPhysics(), + controller: _tabController, + children: [ + PentryPPMCheckListForm( + models: _pentry.ppmCheckLists, + enableValidate: _validate, + ), + PentryCalibrationToolForm( + models: _pentry.calibrationTools, + enableValidate: _validate, + ), + PentryPMKitForm( + models: _pentry.pmKits, + enableValidate: _validate, + ), + PentryInfoForm( + model: _pentry, + enableValidate: _validate, + ), + ], + ), + Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + if (_tabController.index != 0) + ASmallButton( + text: _subtitle.back, + onPressed: () { + _tabController.animateTo( + _tabController.index - 1, + ); + setState(() {}); + }, + ), + const Spacer(), + if (_tabController.index != _tabController.length - 1) + ASmallButton( + text: _subtitle.next, + onPressed: () { + _tabController.animateTo( + _tabController.index + 1, + ); + setState(() {}); + }, + ), + if (_tabController.index == _tabController.length - 1) + ASmallButton( + text: _subtitle.update, + onPressed: _onSubmit, + ), + ], + ), + ), + ) ], - ), - Align( - alignment: Alignment.bottomCenter, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - children: [ - if(_tabController.index != 0) - ASmallButton( - text: _subtitle.back, - onPressed: (){ - _tabController.animateTo(_tabController.index - 1,); - setState(() {}); - }, - ), - const Spacer(), - if(_tabController.index != _tabController.length -1) - ASmallButton( - text: _subtitle.next, - onPressed: (){ - _tabController.animateTo(_tabController.index + 1,); - setState(() {}); - }, - ), - if(_tabController.index == _tabController.length -1) - ASmallButton( - text: _subtitle.update, - onPressed: _onSubmit, - ), - ], - ), - ), - ) - ], - ), - ), - - ], - ) - ), + ), + ), + ], + )), ), ); } } - diff --git a/lib/views/pages/user/visits/pantry/future_edit_pently.dart b/lib/views/pages/user/visits/pantry/future_edit_pently.dart index 161df3ce..1f050f58 100644 --- a/lib/views/pages/user/visits/pantry/future_edit_pently.dart +++ b/lib/views/pages/user/visits/pantry/future_edit_pently.dart @@ -10,8 +10,8 @@ import 'package:test_sa/models/visits/visit.dart'; import 'package:test_sa/views/pages/user/visits/pantry/edit_pentry.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; import 'package:test_sa/views/widgets/loaders/failed_loading.dart'; -class FutureEditPentry extends StatefulWidget { +class FutureEditPentry extends StatefulWidget { final Visit visit; const FutureEditPentry({Key key, this.visit}) : super(key: key); @@ -21,7 +21,6 @@ class FutureEditPentry extends StatefulWidget { } class _FutureEditPentryState extends State { - UserProvider _userProvider; SettingProvider _settingProvider; @override @@ -32,20 +31,17 @@ class _FutureEditPentryState extends State { Subtitle subtitle = AppLocalization.of(context).subtitle; return Scaffold( body: FutureBuilder( - future: RegularVisitsProvider().getPently( - user: _userProvider.user, - host: _settingProvider.host, - id: widget.visit.id - ), - builder: (BuildContext context, AsyncSnapshot snapshot){ - if(snapshot.hasError) { - + future: RegularVisitsProvider().getPently(user: _userProvider.user, host: _settingProvider.host, id: widget.visit.id), + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.hasError) { return FailedLoading( message: subtitle.failedToCompleteRequest, - onReload: (){setState(() {});}, + onReload: () { + setState(() {}); + }, ); } - if(snapshot.hasData){ + if (snapshot.hasData) { return EditPentry( pentry: snapshot.data, visit: widget.visit, diff --git a/lib/views/pages/user/visits/preventive_maintenance_visits_page.dart b/lib/views/pages/user/visits/preventive_maintenance_visits_page.dart index 7c1c57c2..c841bbf3 100644 --- a/lib/views/pages/user/visits/preventive_maintenance_visits_page.dart +++ b/lib/views/pages/user/visits/preventive_maintenance_visits_page.dart @@ -2,7 +2,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/http_status_manger/http_status_manger.dart'; +import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/preventive_maintenance_visits_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; @@ -18,14 +18,15 @@ import 'package:test_sa/views/widgets/buttons/app_icon_button.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/search/visits_search_bar.dart'; import 'package:test_sa/views/widgets/visits/visits_list.dart'; + class PreventiveMaintenanceVisitsPage extends StatefulWidget { static final String id = "/preventive-maintenance-visits"; + @override _PreventiveMaintenanceVisitsPageState createState() => _PreventiveMaintenanceVisitsPageState(); } -class _PreventiveMaintenanceVisitsPageState extends State - with TickerProviderStateMixin{ +class _PreventiveMaintenanceVisitsPageState extends State with TickerProviderStateMixin { PreventiveMaintenanceVisitsProvider _visitsProvider; UserProvider _userProvider; SettingProvider _settingProvider; @@ -57,8 +58,8 @@ class _PreventiveMaintenanceVisitsPageState extends State( context: context, barrierDismissible: false, @@ -151,24 +153,17 @@ class _PreventiveMaintenanceVisitsPageState extends State= 200 && status < 300){ + if (status >= 200 && status < 300) { Fluttertoast.showToast( msg: _subtitle.preventiveMaintenanceUpdatedSuccessfully, toastLength: Toast.LENGTH_LONG, gravity: ToastGravity.BOTTOM, ); - }else{ + } else { Fluttertoast.showToast( - msg: HttpStatusManger.getStatusMessage( - status: status, - subtitle: _subtitle - ), + msg: HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle), toastLength: Toast.LENGTH_LONG, gravity: ToastGravity.BOTTOM, ); @@ -180,7 +175,6 @@ class _PreventiveMaintenanceVisitsPageState extends State _RegularVisitsPageState(); } -class _RegularVisitsPageState extends State - with TickerProviderStateMixin{ +class _RegularVisitsPageState extends State with TickerProviderStateMixin { RegularVisitsProvider _visitsProvider; UserProvider _userProvider; SettingProvider _settingProvider; bool _expandedSearch = false; Subtitle _subtitle; + @override Widget build(BuildContext context) { _visitsProvider = Provider.of(context); @@ -47,8 +49,8 @@ class _RegularVisitsPageState extends State _visitsProvider.reset(); //_visitsProvider.visitsSearch = VisitsSearch(); await _visitsProvider.getVisits( - user: _userProvider.user, - host: _settingProvider.host, + user: _userProvider.user, + host: _settingProvider.host, ); }, child: Stack( @@ -56,8 +58,8 @@ class _RegularVisitsPageState extends State Column( children: [ Container( - color:AColors.primaryColor, - padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), + color: AColors.primaryColor, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), child: Column( children: [ Row( @@ -67,10 +69,7 @@ class _RegularVisitsPageState extends State child: Center( child: Text( _subtitle.preventiveMaintenance, - style: Theme.of(context).textTheme.headline6.copyWith( - color: AColors.white, - fontStyle: FontStyle.italic - ), + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), ), ), ), @@ -78,7 +77,7 @@ class _RegularVisitsPageState extends State duration: Duration(milliseconds: 400), child: AIconButton( key: ValueKey(_expandedSearch), - iconData: _expandedSearch ? Icons.keyboard_arrow_up :Icons.search, + iconData: _expandedSearch ? Icons.keyboard_arrow_up : Icons.search, color: AColors.secondaryColor, buttonSize: 42, backgroundColor: AColors.white, @@ -86,33 +85,34 @@ class _RegularVisitsPageState extends State VisitsSearch _temp = await showModalBottomSheet( context: context, isScrollControlled: true, - builder: (context){ + builder: (context) { return VisitsSearchDialog( initialSearchValue: _visitsProvider.visitsSearch, ); }); - if(_temp != null){ - _visitsProvider.visitsSearch.fromSearch(_temp) ; + if (_temp != null) { + _visitsProvider.visitsSearch.fromSearch(_temp); _visitsProvider.reset(); setState(() {}); } }, ), ), - SizedBox(width: 16,) + SizedBox( + width: 16, + ) ], ), - ], ), ), Visibility( - visible: _visitsProvider.visitsSearch.toSearchString().isNotEmpty, + visible: _visitsProvider.visitsSearch.toMap().isNotEmpty, child: Padding( padding: const EdgeInsets.all(8.0), child: AButton( text: _subtitle.clearSearch, - onPressed: (){ + onPressed: () { _visitsProvider.visitsSearch = VisitsSearch(); _visitsProvider.reset(); setState(() {}); @@ -125,8 +125,8 @@ class _RegularVisitsPageState extends State nextPage: _visitsProvider.nextPage, onLazyLoad: () async { await _visitsProvider.getVisits( - user: _userProvider.user, - host: _settingProvider.host, + user: _userProvider.user, + host: _settingProvider.host, ); }, onEditGroup: (visits) async { @@ -134,10 +134,13 @@ class _RegularVisitsPageState extends State isScrollControlled: true, context: context, builder: (context) { - return UpdateVisitsGroupSheet(visits: visits,title: _subtitle.updateRegularVisits,); + return UpdateVisitsGroupSheet( + visits: visits, + title: _subtitle.updateRegularVisits, + ); }, - )as VisitsGroup; - if(_group != null){ + ) as VisitsGroup; + if (_group != null) { showDialog( context: context, barrierDismissible: false, @@ -148,24 +151,17 @@ class _RegularVisitsPageState extends State ); }, ); - int status = await _visitsProvider.updateGroupOfVisits( - user: _userProvider.user, - host: _settingProvider.host, - group: _group - ); + int status = await _visitsProvider.updateGroupOfVisits(user: _userProvider.user, host: _settingProvider.host, group: _group); Navigator.of(context).pop(); - if(status >= 200 && status < 300){ + if (status >= 200 && status < 300) { Fluttertoast.showToast( - msg: _subtitle.regularVisitsUpdatedSuccessfully, - toastLength: Toast.LENGTH_LONG, - gravity: ToastGravity.BOTTOM, + msg: _subtitle.preventiveMaintenanceUpdatedSuccessfully, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, ); - }else{ + } else { Fluttertoast.showToast( - msg: HttpStatusManger.getStatusMessage( - status: status, - subtitle: _subtitle - ), + msg: HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle), toastLength: Toast.LENGTH_LONG, gravity: ToastGravity.BOTTOM, ); @@ -177,7 +173,6 @@ class _RegularVisitsPageState extends State ), ], ), - ], ), ), diff --git a/lib/views/pages/user/visits/update_visits_group_sheet.dart b/lib/views/pages/user/visits/update_visits_group_sheet.dart index 724f4657..35e3e81a 100644 --- a/lib/views/pages/user/visits/update_visits_group_sheet.dart +++ b/lib/views/pages/user/visits/update_visits_group_sheet.dart @@ -1,24 +1,19 @@ -import 'dart:convert'; -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:test_sa/controllers/localization/localization.dart'; -import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/models/visits/visit.dart'; import 'package:test_sa/models/visits/visits_group.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; -import 'package:test_sa/views/widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; import 'package:test_sa/views/widgets/buttons/app_small_button.dart'; -import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; -import 'package:test_sa/views/widgets/images/one_image_picker.dart'; -import 'package:test_sa/views/widgets/search/filter_item.dart'; +import 'package:test_sa/views/widgets/status/employee/engineers_mune.dart'; import 'package:test_sa/views/widgets/visits/visit_status.dart'; + class UpdateVisitsGroupSheet extends StatefulWidget { final List visits; final String title; + const UpdateVisitsGroupSheet({Key key, this.visits, this.title}) : super(key: key); @override @@ -26,25 +21,26 @@ class UpdateVisitsGroupSheet extends StatefulWidget { } class _UpdateVisitsGroupSheetState extends State { - List status = [ - Lookup(label: "Done", id: 0,), - Lookup(label: "Not Yet", id: 1), - Lookup(label: "On Hold", id: 2,), - ]; - - List taskStatus = [ - Lookup(label: "Passed", id: 0,), - Lookup(label: "Failed", id: 1), - ]; + // List status = [ + // Lookup(name: "Done", id: 0,), + // Lookup(name: "Not Yet", id: 1), + // Lookup(name: "On Hold", id: 2,), + // ]; + // + // List taskStatus = [ + // Lookup(name: "Passed", id: 0,), + // Lookup(name: "Failed", id: 1), + // ]; VisitsGroup _group = VisitsGroup(); - File _image; + + // File _image; Subtitle _subtitle; @override void initState() { super.initState(); _group.visits = widget.visits; - _group.date = DateTime.now(); + //_group.date = DateTime.now(); } @override @@ -72,160 +68,163 @@ class _UpdateVisitsGroupSheetState extends State { ), ASmallButton( text: _subtitle.cancel, - onPressed: (){ + onPressed: () { Navigator.of(context).pop(); }, ), ], ), - - AOneImagePicker( - image: _image, - onPick: (image){ - _image =image; - _group.image = base64Encode(image.readAsBytesSync()); - }, - ), - SizedBox(height: 12 * AppStyle.getScaleFactor(context),), - ATextFormField( - initialValue: _group.jobSheetNumber, - hintText: _subtitle.jobSheetNumber, - style: Theme.of(context).textTheme.headline6, - onSaved: (value){ - _group.jobSheetNumber = value; - }, - ), - SizedBox(height: 8 * AppStyle.getScaleFactor(context),), - ATextFormField( - initialValue: _group.workingHours, - hintText: _subtitle.workingHours, - style: Theme.of(context).textTheme.headline6, - onSaved: (value){ - _group.workingHours = value; - }, + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), ), - SizedBox(height: 8 * AppStyle.getScaleFactor(context),), - ATextFormField( - initialValue: _group.travelingHours, - hintText: _subtitle.travelingHours, - style: Theme.of(context).textTheme.headline6, - onSaved: (value){ - _group.travelingHours = value; + EngineersMenu( + initialValue: _group.engineer, + onSelect: (engineer) { + _group.engineer = engineer; }, ), - SizedBox(height: 8 * AppStyle.getScaleFactor(context),), - Row( - children: [ - Expanded( - child: Text( - "${_subtitle.date} :", - style: Theme.of(context).textTheme.subtitle1, - textScaleFactor: AppStyle.getScaleFactor(context), - ), - ), - ADatePicker( - date: _group.date ?? DateTime.now(), - onDatePicker: (date){ - _group.date = date; - setState(() {}); - }, - ), - ], - ), - // SizedBox(height: 8 * AStyling.getScaleFactor(context),), - Text( - "${_subtitle.status} :", - style: Theme.of(context).textTheme.subtitle1, - textScaleFactor: AppStyle.getScaleFactor(context), - ), - SizedBox(height: 8 * AppStyle.getScaleFactor(context),), - Center( - child: Wrap( - spacing: 10, - runSpacing: 10, - children: List.generate( - status.length, - (index) { - bool isSelected = _group.status == status[index]; - return FilterItem( - isSelected: isSelected, - onSelected: (){ - if(isSelected) - _group.status = null; - else - _group.status = status[index]; - - setState(() {}); - }, - status: status[index], - ); - } - - ), - ), - ), - Text( - "${_subtitle.taskStatus} :", - style: Theme.of(context).textTheme.subtitle1, - textScaleFactor: AppStyle.getScaleFactor(context), + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), ), - SizedBox(height: 8 * AppStyle.getScaleFactor(context),), - Center( - child: Wrap( - spacing: 10, - runSpacing: 10, - children: List.generate( - taskStatus.length, - (index) { - bool isSelected = _group.taskStatus == taskStatus[index]; - return FilterItem( - isSelected: isSelected, - onSelected: (){ - if(isSelected) - _group.taskStatus = null; - else - _group.taskStatus = taskStatus[index]; - - setState(() {}); - }, - status: taskStatus[index], - ); - } - - ), - ), + // AOneImagePicker( + // image: _image, + // onPick: (image){ + // _image =image; + // _group.image = base64Encode(image.readAsBytesSync()); + // }, + // ), + // SizedBox(height: 12 * AppStyle.getScaleFactor(context),), + // ATextFormField( + // initialValue: _group.jobSheetNumber, + // hintText: _subtitle.jobSheetNumber, + // style: Theme.of(context).textTheme.headline6, + // onSaved: (value){ + // _group.jobSheetNumber = value; + // }, + // ), + // SizedBox(height: 8 * AppStyle.getScaleFactor(context),), + // ATextFormField( + // initialValue: _group.workingHours, + // hintText: _subtitle.workingHours, + // style: Theme.of(context).textTheme.headline6, + // onSaved: (value){ + // _group.workingHours = value; + // }, + // ), + // SizedBox(height: 8 * AppStyle.getScaleFactor(context),), + // ATextFormField( + // initialValue: _group.travelingHours, + // hintText: _subtitle.travelingHours, + // style: Theme.of(context).textTheme.headline6, + // onSaved: (value){ + // _group.travelingHours = value; + // }, + // ), + // SizedBox(height: 8 * AppStyle.getScaleFactor(context),), + // Row( + // children: [ + // Expanded( + // child: Text( + // "${_subtitle.date} :", + // style: Theme.of(context).textTheme.subtitle1, + // textScaleFactor: AppStyle.getScaleFactor(context), + // ), + // ), + // ADatePicker( + // date: _group.date ?? DateTime.now(), + // onDatePicker: (date){ + // _group.date = date; + // setState(() {}); + // }, + // ), + // ], + // ), + // // SizedBox(height: 8 * AStyling.getScaleFactor(context),), + // Text( + // "${_subtitle.status} :", + // style: Theme.of(context).textTheme.subtitle1, + // textScaleFactor: AppStyle.getScaleFactor(context), + // ), + // SizedBox(height: 8 * AppStyle.getScaleFactor(context),), + // Center( + // child: Wrap( + // spacing: 10, + // runSpacing: 10, + // children: List.generate( + // status.length, + // (index) { + // bool isSelected = _group.status == status[index]; + // return FilterItem( + // isSelected: isSelected, + // onSelected: (){ + // if(isSelected) + // _group.status = null; + // else + // _group.status = status[index]; + // + // setState(() {}); + // }, + // status: status[index], + // ); + // } + // + // ), + // ), + // ), + // Text( + // "${_subtitle.taskStatus} :", + // style: Theme.of(context).textTheme.subtitle1, + // textScaleFactor: AppStyle.getScaleFactor(context), + // ), + // SizedBox(height: 8 * AppStyle.getScaleFactor(context),), + // Center( + // child: Wrap( + // spacing: 10, + // runSpacing: 10, + // children: List.generate( + // taskStatus.length, + // (index) { + // bool isSelected = _group.taskStatus == taskStatus[index]; + // return FilterItem( + // isSelected: isSelected, + // onSelected: (){ + // if(isSelected) + // _group.taskStatus = null; + // else + // _group.taskStatus = taskStatus[index]; + // + // setState(() {}); + // }, + // status: taskStatus[index], + // ); + // } + // + // ), + // ), + // ), + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), ), - SizedBox(height: 8 * AppStyle.getScaleFactor(context),), Expanded( child: ListView.builder( itemCount: widget.visits.length, - itemBuilder: (context,index){ + itemBuilder: (context, index) { Visit visit = widget.visits[index]; return Container( - padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8), + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8), margin: EdgeInsets.symmetric(vertical: 4), - decoration: BoxDecoration( - color: AColors.primaryColor, - borderRadius: BorderRadius.circular( - AppStyle.getBorderRadius(context) - ), - boxShadow: [ - AppStyle.boxShadow - ] - ), + decoration: BoxDecoration(color: AColors.primaryColor, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [AppStyle.boxShadow]), child: Row( children: [ Expanded( child: Text( - "${_subtitle.sn}: "+visit.deviceSerialNumber ?? _subtitle.noSerialNumberFound, - style: Theme.of(context).textTheme.headline6.copyWith( - color: AColors.white, - fontSize: 16, - fontWeight: FontWeight.bold - ), + "${_subtitle.sn}: " + visit.deviceSerialNumber ?? _subtitle.noSerialNumberFound, + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontSize: 16, fontWeight: FontWeight.bold), ), ), - VisitStatusLabel(visit: visit,) + VisitStatusLabel( + visit: visit, + ) ], ), ); @@ -234,16 +233,12 @@ class _UpdateVisitsGroupSheetState extends State { ), AButton( text: _subtitle.update, - onPressed: (){ - Navigator.of(context).pop(_group); + onPressed: () { + Navigator.of(context).pop(_group); }, ), ], ), - Align( - alignment: Alignment.topRight, - - ), ], ), ); diff --git a/lib/views/pages/user/visits/visit_details.dart b/lib/views/pages/user/visits/visit_details.dart index e191cf67..7fb05200 100644 --- a/lib/views/pages/user/visits/visit_details.dart +++ b/lib/views/pages/user/visits/visit_details.dart @@ -5,7 +5,7 @@ import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/models/visits/visit.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; -import 'package:test_sa/views/pages/user/visits/pantry/future_edit_pently.dart'; +import 'package:test_sa/views/pages/user/visits/pantry/edit_pentry.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/buttons/app_icon_button.dart'; import 'package:test_sa/views/widgets/images/images_list.dart'; @@ -13,97 +13,102 @@ import 'package:test_sa/views/widgets/loaders/image_loader.dart'; import 'package:test_sa/views/widgets/requests/info_row.dart'; import 'package:test_sa/views/widgets/visits/visit_status.dart'; -import '../../../../controllers/providers/api/regular_visits_provider.dart'; - +import '../../../../controllers/providers/api/user_provider.dart'; +import '../../../../models/enums/user_types.dart'; class VisitDetailsPage extends StatelessWidget { - static final String id = "/visit-details"; + static const String id = "/visit-details"; final Visit visit; const VisitDetailsPage({Key key, this.visit}) : super(key: key); @override Widget build(BuildContext context) { - Subtitle _subtitle = AppLocalization.of(context).subtitle; - final regularVisitsProvider = Provider.of(context); + Subtitle subtitle = AppLocalization.of(context).subtitle; + UserProvider userProvider = Provider.of(context); return Scaffold( body: SafeArea( child: Column( children: [ Container( - color:AColors.primaryColor, - padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), + color: AColors.primaryColor, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), child: Row( children: [ - ABackButton(), + const ABackButton(), Expanded( child: Center( child: Text( - _subtitle.visitInformation, - style: Theme.of(context).textTheme.headline6.copyWith( - color: AColors.white, - fontStyle: FontStyle.italic - ), + subtitle.visitInformation, + style: Theme.of(context).textTheme.titleLarge.copyWith(color: AColors.white, fontStyle: FontStyle.italic), ), ), ), - AIconButton( - iconData: Icons.edit, - color: AColors.white, - buttonSize: 42, - backgroundColor: AColors.green, - onPressed: () async { - Navigator.of(context).push( - MaterialPageRoute(builder: (_)=> FutureEditPentry(visit: visit,)) - ); - }, - ), - SizedBox(width: 16,) + if (userProvider?.user?.type == UsersTypes.engineer) + AIconButton( + iconData: Icons.edit, + color: AColors.white, + buttonSize: 42, + backgroundColor: AColors.green, + onPressed: () async { + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => EditPentry( + visit: visit, + pentry: visit.pentry, + ))); + }, + ), + const SizedBox(width: 42) ], ), ), Expanded( child: ListView( - padding: EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric(horizontal: 16), children: [ - SizedBox(height: 8,), + const SizedBox( + height: 8, + ), MaterialButton( padding: EdgeInsets.zero, - onPressed: (){ - Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => Scaffold( - body: InteractiveViewer( - child: Center( - child: ImageLoader( - url: visit.images.first, - boxFit: BoxFit.contain, + onPressed: () { + if (visit.images.isEmpty || (visit.images?.first?.isEmpty ?? false)) { + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => Scaffold( + body: InteractiveViewer( + child: Center( + child: ImageLoader( + url: visit.images.first, + boxFit: BoxFit.contain, + ), ), ), - ), - ) - ) - ); + ))); + } }, child: SizedBox( height: 140 * AppStyle.getScaleFactor(context), width: MediaQuery.of(context).size.width, child: ImageLoader( - url: visit.images.isEmpty ? " ":visit.images.first, + url: visit.images.isEmpty ? " " : visit.images.first, boxFit: BoxFit.cover, ), ), ), - SizedBox(height: 8,), + const SizedBox( + height: 8, + ), SizedBox( - height: 60* AppStyle.getScaleFactor(context), + height: 60 * AppStyle.getScaleFactor(context), child: ImagesList( images: visit.images, ), ), - SizedBox(height: 8,), + const SizedBox( + height: 8, + ), RequestInfoRow( - title: _subtitle.code, + title: subtitle.code, info: visit.serialNumber, ), RequestInfoRow( @@ -111,54 +116,50 @@ class VisitDetailsPage extends StatelessWidget { info: visit.deviceNumber, ), RequestInfoRow( - title: _subtitle.deviceSN, + title: subtitle.deviceName, + content: visit.deviceEnglishName, + ), + RequestInfoRow( + title: subtitle.deviceSN, info: visit.deviceSerialNumber, ), - RequestInfoRow( - title: _subtitle.expectDate, + title: subtitle.expectDate, info: visit.expectDate, ), RequestInfoRow( - title: _subtitle.actualDate, + title: subtitle.actualDate, info: visit.actualDate, ), Row( children: [ Expanded( child: Text( - "${_subtitle.status} : ", - style: Theme.of(context).textTheme.subtitle1.copyWith( - fontWeight: FontWeight.bold - ), + "${subtitle.status} : ", + style: Theme.of(context).textTheme.titleMedium.copyWith(fontWeight: FontWeight.bold), textScaleFactor: AppStyle.getScaleFactor(context), ), ), - VisitStatusLabel(visit: visit,), + VisitStatusLabel( + visit: visit, + ), ], ), - - Divider(color: Theme.of(context).primaryColor,), + Divider( + color: Theme.of(context).primaryColor, + ), RequestInfoRow( - title: _subtitle.contactStatus, + title: subtitle.contactStatus, info: visit.assignTo, ), RequestInfoRow( - title: _subtitle.engineerName, + title: subtitle.engineerName, info: visit.employName, ), RequestInfoRow( - title: _subtitle.hospital, + title: subtitle.hospital, content: visit.hospitalName, ), - RequestInfoRow( - title: _subtitle.deviceArName, - content: visit.deviceArabicName, - ), - RequestInfoRow( - title: _subtitle.deviceEnName, - content: visit.deviceEnglishName, - ), ], ), ), diff --git a/lib/views/widgets/app_name_bar.dart b/lib/views/widgets/app_name_bar.dart index 8aebd901..9979dace 100644 --- a/lib/views/widgets/app_name_bar.dart +++ b/lib/views/widgets/app_name_bar.dart @@ -1,20 +1,18 @@ import 'package:flutter/material.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; + class AppNameBar extends StatelessWidget { @override Widget build(BuildContext context) { return Container( height: 50 * AppStyle.getScaleFactor(context), - color:AColors.primaryColor, + color: AColors.primaryColor, padding: const EdgeInsets.all(8.0), child: Center( child: Text( "Test SA", - style: Theme.of(context).textTheme.headline6.copyWith( - color: AColors.white, - fontStyle: FontStyle.italic - ), + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), ), ), ); diff --git a/lib/views/widgets/buttons/app_back_button.dart b/lib/views/widgets/buttons/app_back_button.dart index a7ce9c2b..ef26325a 100644 --- a/lib/views/widgets/buttons/app_back_button.dart +++ b/lib/views/widgets/buttons/app_back_button.dart @@ -7,7 +7,7 @@ class ABackButton extends StatelessWidget { final VoidCallback onPressed; final IconData icon; - const ABackButton({Key key, this.onPressed,this.icon}) : super(key: key); + const ABackButton({Key key, this.onPressed, this.icon}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/views/widgets/buttons/app_button.dart b/lib/views/widgets/buttons/app_button.dart index 6c0459d5..c3fd1680 100644 --- a/lib/views/widgets/buttons/app_button.dart +++ b/lib/views/widgets/buttons/app_button.dart @@ -27,7 +27,7 @@ class AButton extends StatelessWidget { onPressed: onPressed, child: Text( text ?? "", - style: textStyle ?? Theme.of(context).textTheme.subtitle2.copyWith(color: AColors.white, fontSize: 14,fontWeight: FontWeight.w600), + style: textStyle ?? Theme.of(context).textTheme.subtitle2.copyWith(color: AColors.white, fontSize: 14, fontWeight: FontWeight.w600), textScaleFactor: AppStyle.getScaleFactor(context), ), ), diff --git a/lib/views/widgets/buttons/app_flat_button.dart b/lib/views/widgets/buttons/app_flat_button.dart index 903b05e2..946a167f 100644 --- a/lib/views/widgets/buttons/app_flat_button.dart +++ b/lib/views/widgets/buttons/app_flat_button.dart @@ -1,5 +1,5 @@ -import 'package:test_sa/views/app_style/sizing.dart'; import 'package:flutter/material.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; class AFlatButton extends StatelessWidget { final String text; @@ -8,19 +8,20 @@ class AFlatButton extends StatelessWidget { final EdgeInsets padding; final VoidCallback onPressed; - const AFlatButton({Key key, this.text, this.textColor,this.style ,this.onPressed,this.padding}) : super(key: key); + const AFlatButton({Key key, this.text, this.textColor, this.style, this.onPressed, this.padding}) : super(key: key); + @override Widget build(BuildContext context) { return TextButton( - style: TextButton.styleFrom( - foregroundColor: this.textColor ?? Colors.black, padding: padding, - ), - onPressed: onPressed, - child: Text( - text??"", - style: style ?? Theme.of(context).textTheme.bodyText1, - textScaleFactor: AppStyle.getScaleFactor(context), - ) - ); + style: TextButton.styleFrom( + foregroundColor: this.textColor ?? Colors.black, + padding: padding, + ), + onPressed: onPressed, + child: Text( + text ?? "", + style: style ?? Theme.of(context).textTheme.bodyText1, + textScaleFactor: AppStyle.getScaleFactor(context), + )); } } diff --git a/lib/views/widgets/buttons/app_icon_button.dart b/lib/views/widgets/buttons/app_icon_button.dart index 07e9c9a3..139d70ca 100644 --- a/lib/views/widgets/buttons/app_icon_button.dart +++ b/lib/views/widgets/buttons/app_icon_button.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; -class AIconButton extends StatelessWidget { +class AIconButton extends StatelessWidget { final IconData iconData; final Color color; final Color backgroundColor; @@ -11,16 +11,7 @@ class AIconButton extends StatelessWidget { final double iconSize; final double buttonSize; - - const AIconButton({ - Key key, - this.iconData, - this.onPressed, - this.color, - this.iconSize, - this.buttonSize = 54, - this.backgroundColor - }) : super(key: key); + const AIconButton({Key key, this.iconData, this.onPressed, this.color, this.iconSize, this.buttonSize = 54, this.backgroundColor}) : super(key: key); @override Widget build(BuildContext context) { @@ -30,12 +21,8 @@ class AIconButton extends StatelessWidget { child: ElevatedButton( style: ElevatedButton.styleFrom( padding: EdgeInsets.zero, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - (AppStyle.borderRadius - 4) * AppStyle.getScaleFactor(context) - ) - ), - backgroundColor: backgroundColor ?? AColors.onPrimaryColor, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular((AppStyle.borderRadius - 4) * AppStyle.getScaleFactor(context))), + backgroundColor: backgroundColor ?? AColors.onPrimaryColor, ), onPressed: onPressed, child: FaIcon( diff --git a/lib/views/widgets/buttons/app_icon_button2.dart b/lib/views/widgets/buttons/app_icon_button2.dart index 1a9bc78e..1726a375 100644 --- a/lib/views/widgets/buttons/app_icon_button2.dart +++ b/lib/views/widgets/buttons/app_icon_button2.dart @@ -1,8 +1,8 @@ -import 'package:test_sa/views/app_style/sizing.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -class AIconButton2 extends StatelessWidget { +import 'package:test_sa/views/app_style/sizing.dart'; +class AIconButton2 extends StatelessWidget { final IconData iconData; final Color color; final VoidCallback onPressed; diff --git a/lib/views/widgets/buttons/app_outlined_button.dart b/lib/views/widgets/buttons/app_outlined_button.dart index ddfb3042..b7e18bd2 100644 --- a/lib/views/widgets/buttons/app_outlined_button.dart +++ b/lib/views/widgets/buttons/app_outlined_button.dart @@ -16,11 +16,7 @@ class AOutLinedButton extends StatelessWidget { return OutlinedButton( style: ElevatedButton.styleFrom( padding: padding ?? EdgeInsets.symmetric(vertical: 12), - textStyle: textStyle ?? Theme - .of(context) - .textTheme - .subtitle2 - .copyWith(fontSize: 18), + textStyle: textStyle ?? Theme.of(context).textTheme.subtitle2.copyWith(fontSize: 18), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context))), ), onPressed: onPressed, @@ -29,11 +25,7 @@ class AOutLinedButton extends StatelessWidget { Expanded( child: Text( text ?? "", - style: Theme - .of(context) - .textTheme - .subtitle2 - .copyWith(color: AColors.primaryColor, fontSize: 14, fontWeight: FontWeight.w600), + style: Theme.of(context).textTheme.subtitle2.copyWith(color: AColors.primaryColor, fontSize: 14, fontWeight: FontWeight.w600), textAlign: TextAlign.center, textScaleFactor: AppStyle.getScaleFactor(context), ), diff --git a/lib/views/widgets/buttons/app_small_button.dart b/lib/views/widgets/buttons/app_small_button.dart index b2f71626..15ad3cfd 100644 --- a/lib/views/widgets/buttons/app_small_button.dart +++ b/lib/views/widgets/buttons/app_small_button.dart @@ -1,5 +1,5 @@ -import 'package:test_sa/views/app_style/sizing.dart'; import 'package:flutter/material.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; class ASmallButton extends StatelessWidget { final String text; @@ -8,26 +8,21 @@ class ASmallButton extends StatelessWidget { final EdgeInsets padding; final VoidCallback onPressed; - const ASmallButton({Key key, this.text, this.style ,this.onPressed,this.padding, this.color}) : super(key: key); + const ASmallButton({Key key, this.text, this.style, this.onPressed, this.padding, this.color}) : super(key: key); + @override Widget build(BuildContext context) { return ElevatedButton( - style: ElevatedButton.styleFrom( - padding: padding, - primary: color ?? Theme.of(context).primaryColor, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8) + style: ElevatedButton.styleFrom( + padding: padding, + primary: color ?? Theme.of(context).primaryColor, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), ), - ), - child: Text( - text??"", - style: style ?? Theme.of(context).textTheme.bodyText1.copyWith( - color: color == Colors.white - ? Theme.of(context).primaryColor : Colors.white + child: Text( + text ?? "", + style: style ?? Theme.of(context).textTheme.bodyText1.copyWith(color: color == Colors.white ? Theme.of(context).primaryColor : Colors.white), + textScaleFactor: AppStyle.getScaleFactor(context), ), - textScaleFactor: AppStyle.getScaleFactor(context), - ), - onPressed: onPressed - ); + onPressed: onPressed); } } diff --git a/lib/views/widgets/custom_clip_path/carve_in_image.dart b/lib/views/widgets/custom_clip_path/carve_in_image.dart index a9f72b08..9b4783c1 100644 --- a/lib/views/widgets/custom_clip_path/carve_in_image.dart +++ b/lib/views/widgets/custom_clip_path/carve_in_image.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; class CarveInImage extends CustomClipper { final double gab; - var radius=10.0; + var radius = 10.0; CarveInImage(this.gab); @@ -10,14 +10,14 @@ class CarveInImage extends CustomClipper { Path getClip(Size size) { Path path = Path(); path.lineTo(0, size.height); - path.lineTo(size.width/2 - gab / 2, size.height); - path.arcToPoint(Offset(size.width/2 + gab / 2, size.height), - radius: Radius.circular(gab/2)); + path.lineTo(size.width / 2 - gab / 2, size.height); + path.arcToPoint(Offset(size.width / 2 + gab / 2, size.height), radius: Radius.circular(gab / 2)); path.lineTo(size.width, size.height); path.lineTo(size.width, 0); path.lineTo(0, 0); return path; } + @override bool shouldReclip(CustomClipper oldClipper) => true; -} \ No newline at end of file +} diff --git a/lib/views/widgets/date_and_time/date_picker.dart b/lib/views/widgets/date_and_time/date_picker.dart index ee68b716..54c4ef8c 100644 --- a/lib/views/widgets/date_and_time/date_picker.dart +++ b/lib/views/widgets/date_and_time/date_picker.dart @@ -16,24 +16,15 @@ class ADatePicker extends StatelessWidget { foregroundColor: Colors.white, textStyle: Theme.of(context).textTheme.subtitle2, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - 12 * AppStyle.getScaleFactor(context) - ), + borderRadius: BorderRadius.circular(12 * AppStyle.getScaleFactor(context)), ), ), child: Text( - date == null ? "Pick Date" : - date.toString().split(" ").first, - style: Theme.of(context).textTheme.subtitle2, + date == null ? "Pick Date" : date.toString().split(" ").first, textScaleFactor: AppStyle.getScaleFactor(context), ), onPressed: () async { - DateTime picked = await showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: from ?? DateTime.now(), - lastDate: to ?? DateTime.now().add(Duration(days: 365)) - ); + DateTime picked = await showDatePicker(context: context, initialDate: DateTime.now(), firstDate: from ?? DateTime.now(), lastDate: to ?? DateTime.now().add(Duration(days: 365))); onDatePicker(picked); }, ); diff --git a/lib/views/widgets/date_and_time/from_to_date_bar.dart b/lib/views/widgets/date_and_time/from_to_date_bar.dart index 4ef79e81..fb222b68 100644 --- a/lib/views/widgets/date_and_time/from_to_date_bar.dart +++ b/lib/views/widgets/date_and_time/from_to_date_bar.dart @@ -4,6 +4,7 @@ import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'date_picker.dart'; + class FromToDateBar extends StatefulWidget { final DateTime from; final DateTime to; @@ -11,6 +12,7 @@ class FromToDateBar extends StatefulWidget { final Function(DateTime) onPickTo; const FromToDateBar({Key key, this.from, this.to, this.onPickFrom, this.onPickTo}) : super(key: key); + @override _FromToDateBarState createState() => _FromToDateBarState(); } @@ -32,22 +34,18 @@ class _FromToDateBarState extends State { return Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( _subtitle.from, - style: Theme.of(context).textTheme.bodyText1.copyWith( - fontSize: 12, - fontWeight: FontWeight.normal - ), + style: Theme.of(context).textTheme.bodyText1.copyWith(fontSize: 12, fontWeight: FontWeight.normal), textScaleFactor: AppStyle.getScaleFactor(context), ), ADatePicker( date: _from, from: DateTime(1950), - onDatePicker: (date){ + onDatePicker: (date) { _from = date; setState(() {}); widget.onPickFrom(date); @@ -60,16 +58,13 @@ class _FromToDateBarState extends State { children: [ Text( _subtitle.to, - style: Theme.of(context).textTheme.bodyText1.copyWith( - fontSize: 12, - fontWeight: FontWeight.normal - ), + style: Theme.of(context).textTheme.bodyText1.copyWith(fontSize: 12, fontWeight: FontWeight.normal), textScaleFactor: AppStyle.getScaleFactor(context), ), ADatePicker( date: _to, from: DateTime(1950), - onDatePicker: (date){ + onDatePicker: (date) { _to = date; setState(() {}); widget.onPickTo(date); diff --git a/lib/views/widgets/date_and_time/time_picker.dart b/lib/views/widgets/date_and_time/time_picker.dart new file mode 100644 index 00000000..63648225 --- /dev/null +++ b/lib/views/widgets/date_and_time/time_picker.dart @@ -0,0 +1,69 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; + +class ADateTimePicker extends StatelessWidget { + final DateTime date; + final DateTime from; + final DateTime to; + final Function(DateTime) onDateTimePicker; + + const ADateTimePicker({Key key, this.date, this.onDateTimePicker, this.from, this.to}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + textStyle: Theme.of(context).textTheme.subtitle2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12 * AppStyle.getScaleFactor(context)), + ), + ), + child: Text( + date == null ? "Pick Time" : date.toString().substring(0, date.toString().lastIndexOf(":")), + textScaleFactor: AppStyle.getScaleFactor(context), + ), + onPressed: () async { + // TimeOfDay picked = await showTimePicker(context: context, initialTime: TimeOfDay.now()); + onDateTimePicker(await showDateTimePicker(context: context, initialDate: date, firstDate: from, lastDate: to)); + }, + ); + } +} + +Future showDateTimePicker({ + BuildContext context, + DateTime initialDate, + DateTime firstDate, + DateTime lastDate, +}) async { + initialDate ??= DateTime.now(); + firstDate ??= initialDate.subtract(const Duration(days: 365 * 100)); + lastDate ??= firstDate.add(const Duration(days: 365 * 200)); + + final DateTime selectedDate = await showDatePicker( + context: context, + initialDate: initialDate, + firstDate: firstDate, + lastDate: lastDate, + ); + + if (selectedDate == null) return null; + + if (!context.mounted) return selectedDate; + + final TimeOfDay selectedTime = await showTimePicker( + context: context, + initialTime: TimeOfDay.fromDateTime(selectedDate), + ); + + return selectedTime == null + ? selectedDate + : DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); +} diff --git a/lib/views/widgets/departments/department_item.dart b/lib/views/widgets/departments/department_item.dart index 4ac240e9..c578ba17 100644 --- a/lib/views/widgets/departments/department_item.dart +++ b/lib/views/widgets/departments/department_item.dart @@ -2,36 +2,33 @@ import 'package:flutter/material.dart'; import 'package:test_sa/models/department.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; + class DepartmentItem extends StatelessWidget { final Department department; final Function(Department) onPressed; const DepartmentItem({Key key, this.department, this.onPressed}) : super(key: key); + @override Widget build(BuildContext context) { return Padding( - padding: EdgeInsets.symmetric(horizontal: 16,vertical: 6), + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 6), child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: AColors.primaryColor, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - AppStyle.getBorderRadius(context) - ), + borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), ), ), - onPressed: (){ + onPressed: () { onPressed(department); }, child: ListTile( title: Text( - department.name ?? "", - style: Theme.of(context).textTheme.subtitle1.copyWith( - color: AColors.white - ), + department.name ?? "", + style: Theme.of(context).textTheme.subtitle1.copyWith(color: AColors.white), textDirection: TextDirection.rtl, ), - ), ), ); diff --git a/lib/views/widgets/departments/single_department_picker.dart b/lib/views/widgets/departments/single_department_picker.dart index e5fb916b..c1d56fdd 100644 --- a/lib/views/widgets/departments/single_department_picker.dart +++ b/lib/views/widgets/departments/single_department_picker.dart @@ -10,8 +10,10 @@ import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/loaders/no_item_found.dart'; import '../app_text_form_field.dart'; + class SingleDepartmentPicker extends StatefulWidget { static final String id = "/single-Department-Picker"; + @override _SingleDepartmentPickerState createState() => _SingleDepartmentPickerState(); } @@ -21,12 +23,13 @@ class _SingleDepartmentPickerState extends State { SettingProvider _settingProvider; List _searchableList = []; bool _firstTime = true; + @override Widget build(BuildContext context) { _departmentsProvider = Provider.of(context); _settingProvider = Provider.of(context); Subtitle _subtitle = AppLocalization.of(context).subtitle; - if(_firstTime && _departmentsProvider.departments != null){ + if (_firstTime && _departmentsProvider.departments != null) { _searchableList.addAll(_departmentsProvider.departments); _firstTime = false; } @@ -45,40 +48,40 @@ class _SingleDepartmentPickerState extends State { }, child: Column( children: [ - SizedBox(height: 48,), + SizedBox( + height: 48, + ), Padding( - padding: const EdgeInsets.symmetric(vertical: 8,horizontal: 16), + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), child: ATextFormField( hintText: _subtitle.searchByName, - style: Theme.of(context).textTheme.headline6, + style: Theme.of(context).textTheme.headline6, suffixIcon: Icon(Icons.search_rounded), - onChange: (value){ + onChange: (value) { _searchableList.clear(); - _searchableList.addAll(_departmentsProvider.departments.where( - (element) => element.name.toLowerCase().contains( - value.toLowerCase() - ) - ).toList()); + _searchableList.addAll(_departmentsProvider.departments.where((element) => element.name.toLowerCase().contains(value.toLowerCase())).toList()); setState(() {}); }, ), ), Expanded( - child: _searchableList.isEmpty ? - NoItemFound(message: _subtitle.noUniteFound,): - ListView.builder( - padding: EdgeInsets.zero, - shrinkWrap: true, - itemCount: _searchableList.length, - itemBuilder: (listContext,itemIndex){ - return DepartmentItem( - department: _searchableList[itemIndex], - onPressed: (hospital){ - Navigator.of(context).pop(hospital); - }, - ); - }, - ), + child: _searchableList.isEmpty + ? NoItemFound( + message: _subtitle.noUniteFound, + ) + : ListView.builder( + padding: EdgeInsets.zero, + shrinkWrap: true, + itemCount: _searchableList.length, + itemBuilder: (listContext, itemIndex) { + return DepartmentItem( + department: _searchableList[itemIndex], + onPressed: (hospital) { + Navigator.of(context).pop(hospital); + }, + ); + }, + ), ), ], ), diff --git a/lib/views/widgets/device_trancfer/device_transfer_info_section.dart b/lib/views/widgets/device_trancfer/device_transfer_info_section.dart index 169e16f1..3bea8ba9 100644 --- a/lib/views/widgets/device_trancfer/device_transfer_info_section.dart +++ b/lib/views/widgets/device_trancfer/device_transfer_info_section.dart @@ -1,18 +1,25 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/models/device/device_transfer_info.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/widgets/loaders/image_loader.dart'; import 'package:test_sa/views/widgets/requests/info_row.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart'; + +import '../../../controllers/providers/api/user_provider.dart'; + class DeviceTransferInfoSection extends StatelessWidget { final DeviceTransferInfo info; + final bool isSender; final VoidCallback onEdit; - const DeviceTransferInfoSection({Key key, this.info, this.onEdit}) : super(key: key); + const DeviceTransferInfoSection({Key key, this.info, this.onEdit, this.isSender}) : super(key: key); @override Widget build(BuildContext context) { + info.userName = Provider.of(context).user.username; final subtitle = AppLocalization.of(context).subtitle; + print("url:${info.signature}"); return Column( children: [ RequestInfoRow( @@ -20,13 +27,13 @@ class DeviceTransferInfoSection extends StatelessWidget { info: info.client.name, ), RequestInfoRow( - title: subtitle.unite, + title: subtitle.department, info: info.department.name, ), - RequestInfoRow( - title: subtitle.engineerName, - info: info.name, - ), + // RequestInfoRow( + // title: isSender ? "Sender Name " : "Receiver Name", + // info: info.userName, + // ), RequestInfoRow( title: subtitle.workingHours, info: info.workingHours, @@ -39,21 +46,22 @@ class DeviceTransferInfoSection extends StatelessWidget { title: "Comment", info: info.comment, ), + RequestInfoRow( + title: "Assigned Engineer", + info: info.assignedEmployeeName, + ), RequestInfoRow( title: "Signature", - info: info.signature?.isEmpty != false - ? subtitle.noDateFound : null, - contentWidget: info.signature?.isEmpty != false ? null : - ImageLoader( - url: info.signature, - ), + info: info.signature?.isEmpty != false ? subtitle.noDateFound : null, + contentWidget: info.signature?.isEmpty != false + ? null + : ImageLoader( + url: info.signature, + ), ), RequestInfoRow( title: subtitle.status, - infoWidget: StatusLabel( - label: info.status?.label, - color: AColors.getGasStatusColor(info.status?.id) - ), + infoWidget: StatusLabel(label: info.status?.name, color: AColors.getGasStatusColor(info.status?.id)), ), ], ); diff --git a/lib/views/widgets/device_trancfer/device_transfer_item.dart b/lib/views/widgets/device_trancfer/device_transfer_item.dart index 0cd2adbf..b2a923b7 100644 --- a/lib/views/widgets/device_trancfer/device_transfer_item.dart +++ b/lib/views/widgets/device_trancfer/device_transfer_item.dart @@ -1,52 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/models/device/device_transfer.dart'; -import 'package:test_sa/models/enums/user_types.dart'; -import 'package:test_sa/models/gas_refill/gas_refill_model.dart'; -import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/models/user.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; -import 'package:test_sa/views/pages/user/requests/report/create_service_report.dart'; -import 'package:test_sa/views/pages/user/requests/report/future_service_report.dart'; -import 'package:test_sa/views/widgets/loaders/image_loader.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; + class DeviceTransferItem extends StatelessWidget { final int index; final DeviceTransfer item; final Function(DeviceTransfer) onPressed; + const DeviceTransferItem({Key key, this.item, this.onPressed, this.index}) : super(key: key); @override Widget build(BuildContext context) { Subtitle _subtitle = AppLocalization.of(context).subtitle; - User _user = Provider.of(context,listen: false).user; - Color itemColor = index % 2 == 0 - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onPrimary; - Color onItemColor = index % 2 != 0 - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onPrimary; + User _user = Provider.of(context, listen: false).user; + Color itemColor = index % 2 == 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; + Color onItemColor = index % 2 != 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: ElevatedButton( - style: ElevatedButton.styleFrom( - padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8), - backgroundColor: itemColor, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - AppStyle.getBorderRadius(context) - ), - ), - ), + style: ElevatedButton.styleFrom( + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8), + backgroundColor: itemColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), + ), + ), //padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8), - onPressed: (){ + onPressed: () { onPressed(item); }, child: Column( @@ -60,28 +48,39 @@ class DeviceTransferItem extends StatelessWidget { children: [ Text( item.title ?? "-----", - style: Theme.of(context).textTheme.headline6.copyWith( - color: onItemColor, - fontSize: 16, - fontWeight: FontWeight.bold - ), + style: Theme.of(context).textTheme.headline6.copyWith(color: onItemColor, fontSize: 16, fontWeight: FontWeight.bold), + ), + Divider( + color: onItemColor, + ), + Text( + item.device?.number ?? "-----", + style: Theme.of(context).textTheme.headline6.copyWith(color: onItemColor, fontSize: 16, fontWeight: FontWeight.bold), + ), + Divider( + color: onItemColor, + ), + Text( + item.device.assetName ?? "", + style: Theme.of(context).textTheme.headline6.copyWith(color: onItemColor, fontSize: 16, fontWeight: FontWeight.bold), + ), + Divider( + color: onItemColor, ), - Divider(color: onItemColor,), Row( children: [ Expanded( child: Text( _subtitle.from, style: Theme.of(context).textTheme.subtitle2.copyWith( - color: onItemColor, - ), + color: onItemColor, + ), ), ), - StatusLabel( - color: AColors.getRequestStatusColor(item.sender.status?.id), - label: item.sender.status?.label, - ) - + StatusLabel( + color: AColors.getRequestStatusColor(item.sender.status?.id), + label: item.sender.status?.name, + ) ], ), //const SizedBox(height: 8,), @@ -91,36 +90,36 @@ class DeviceTransferItem extends StatelessWidget { child: Text( item.sender.client.name, style: Theme.of(context).textTheme.subtitle2.copyWith( - color: onItemColor, - ), + color: onItemColor, + ), ), ), - - ], ), - Text( - item.sender.department.name, - style: Theme.of(context).textTheme.bodySmall.copyWith( - color: onItemColor, + if (item.sender.department.id != null) + Text( + item.sender.department.name, + style: Theme.of(context).textTheme.bodySmall.copyWith( + color: onItemColor, + ), ), + Divider( + color: onItemColor, ), - Divider(color: onItemColor,), Row( children: [ Expanded( child: Text( _subtitle.to, style: Theme.of(context).textTheme.subtitle2.copyWith( - color: onItemColor, - ), + color: onItemColor, + ), ), ), StatusLabel( color: AColors.getRequestStatusColor(item.receiver.status?.id), - label: item.receiver.status?.label, + label: item.receiver.status?.name, ) - ], ), //const SizedBox(height: 8,), @@ -130,25 +129,23 @@ class DeviceTransferItem extends StatelessWidget { child: Text( item.receiver.client.name, style: Theme.of(context).textTheme.subtitle2.copyWith( - color: onItemColor, - ), + color: onItemColor, + ), ), ), - - ], ), - Text( - item.receiver.department.name, - style: Theme.of(context).textTheme.bodySmall.copyWith( - color: onItemColor, + if (item.receiver.department.id != null) + Text( + item.receiver.department.name, + style: Theme.of(context).textTheme.bodySmall.copyWith( + color: onItemColor, + ), ), - ), //Divider(color: onItemColor,), ], ), ), - ], ), ], diff --git a/lib/views/widgets/device_trancfer/device_transfer_list.dart b/lib/views/widgets/device_trancfer/device_transfer_list.dart index 18bee922..a90c74aa 100644 --- a/lib/views/widgets/device_trancfer/device_transfer_list.dart +++ b/lib/views/widgets/device_trancfer/device_transfer_list.dart @@ -6,6 +6,7 @@ import 'package:test_sa/views/pages/device_transfer/device_transfer_details.dart import 'package:test_sa/views/widgets/device_trancfer/device_transfer_item.dart'; import 'package:test_sa/views/widgets/loaders/lazy_loading.dart'; import 'package:test_sa/views/widgets/loaders/no_item_found.dart'; + class DeviceTransferList extends StatelessWidget { final List items; final bool nextPage; @@ -15,32 +16,28 @@ class DeviceTransferList extends StatelessWidget { @override Widget build(BuildContext context) { - - if(items.length == 0){ + if (items.isEmpty) { Subtitle subtitle = AppLocalization.of(context).subtitle; - return NoItemFound(message: subtitle.noServiceRequestFound,); + return NoItemFound( + message: subtitle.noServiceRequestFound, + ); } return LazyLoading( nextPage: nextPage, onLazyLoad: onLazyLoad, child: ListView.builder( - //physics: const BouncingScrollPhysics(), - itemCount: items.length, - padding: const EdgeInsets.symmetric(horizontal: 16,vertical: 8), - itemBuilder: (context,itemIndex){ + //physics: const BouncingScrollPhysics(), + itemCount: items.length, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + itemBuilder: (context, itemIndex) { return DeviceTransferItem( index: itemIndex, item: items[itemIndex], - onPressed: (model){ - Navigator.of(context).push( - MaterialPageRoute( - builder: (_)=> DeviceTransferDetails(model: model,) - ) - ); + onPressed: (model) async { + Navigator.of(context).push(MaterialPageRoute(builder: (_) => DeviceTransferDetails(model: model))); }, ); - } - ), + }), ); } } diff --git a/lib/views/widgets/dialogs/dialog.dart b/lib/views/widgets/dialogs/dialog.dart index fa20a8f3..bf9db495 100644 --- a/lib/views/widgets/dialogs/dialog.dart +++ b/lib/views/widgets/dialogs/dialog.dart @@ -1,7 +1,8 @@ -import 'package:test_sa/controllers/localization/localization.dart'; -import 'package:test_sa/models/subtitle.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:test_sa/controllers/localization/localization.dart'; +import 'package:test_sa/models/subtitle.dart'; + class AAlertDialog extends StatelessWidget { final String title; final String content; @@ -12,12 +13,8 @@ class AAlertDialog extends StatelessWidget { Widget build(BuildContext context) { Subtitle _subtitle = AppLocalization.of(context).subtitle; return CupertinoAlertDialog( - title: title != null - ? Text(title) - : null, - content: content != null - ? Text(content) - : null, + title: title != null ? Text(title) : null, + content: content != null ? Text(content) : null, actions: [ TextButton( child: Text(_subtitle.confirm), diff --git a/lib/views/widgets/drawer/drawer_item.dart b/lib/views/widgets/drawer/drawer_item.dart index 1bbc2474..70e072ea 100644 --- a/lib/views/widgets/drawer/drawer_item.dart +++ b/lib/views/widgets/drawer/drawer_item.dart @@ -25,7 +25,7 @@ class DrawerItem extends StatelessWidget { onPressed: onPressed, child: Row( children: [ - Icon(icon, color: AColors.grey3A,size: 20), + Icon(icon, color: AColors.grey3A, size: 20), 12.width, Text( title, @@ -33,7 +33,7 @@ class DrawerItem extends StatelessWidget { textScaleFactor: AppStyle.getScaleFactor(context), ), ], - ).paddingOnly(left: 20,right: 20), + ).paddingOnly(left: 20, right: 20), ), ); } diff --git a/lib/views/widgets/e_signature/e_signature.dart b/lib/views/widgets/e_signature/e_signature.dart index c48ce9b5..2c5dcc41 100644 --- a/lib/views/widgets/e_signature/e_signature.dart +++ b/lib/views/widgets/e_signature/e_signature.dart @@ -9,7 +9,8 @@ class ESignature extends StatefulWidget { final String oldSignature; final Uint8List newSignature; final Function(Uint8List) onSaved; - const ESignature({Key key, this.oldSignature, this.onSaved, this.newSignature}) : super(key: key); + final Function(Uint8List) onChange; + const ESignature({Key key, this.oldSignature, this.onSaved, this.onChange, this.newSignature}) : super(key: key); @override State createState() => _ESignatureState(); @@ -28,7 +29,7 @@ class _ESignatureState extends State { bool _unpaint = false; @override void initState() { - if(widget.newSignature != null) { + if (widget.newSignature != null) { signature = widget.newSignature; } // TODO: implement initState @@ -45,71 +46,75 @@ class _ESignatureState extends State { Widget build(BuildContext context) { return Column( children: [ - if(widget.oldSignature != null || signature != null) - Container( - width: MediaQuery.of(context).size.width, - padding: const EdgeInsets.only(bottom: 8), - height: 90 * AppStyle.getScaleFactor(context), - child: signature != null ? - Image.memory(signature): - ImageLoader( - boxFit: BoxFit.contain, - url: widget.oldSignature) - ), - FormField( - onSaved: (_) async { - widget.onSaved(signature); - }, - builder: (FormFieldState state) { - return Column( - children: [ - Container( - width: MediaQuery.of(context).size.width, - padding: const EdgeInsets.symmetric( - horizontal: 16 - ), - decoration: BoxDecoration( - color: Colors.white, - border: Border.all(color:AColors.black), - borderRadius: BorderRadius.circular( - AppStyle.borderRadius * AppStyle.getScaleFactor(context) - ), - boxShadow: const [ - AppStyle.boxShadow - ] - ), - child: AbsorbPointer( - absorbing: _unpaint, - child: Signature( - controller: _controller, - height: 160 * AppStyle.getScaleFactor(context), - backgroundColor: Colors.transparent, - ), - ), + if (widget.oldSignature != null || signature != null) + Container( + width: MediaQuery.of(context).size.width, + padding: const EdgeInsets.only(bottom: 8), + height: 90 * AppStyle.getScaleFactor(context), + child: signature != null ? Image.memory(signature) : ImageLoader(boxFit: BoxFit.contain, url: widget.oldSignature)), + FormField(onSaved: (_) async { + widget.onSaved(signature); + }, builder: (FormFieldState state) { + return Column( + children: [ + Container( + width: MediaQuery.of(context).size.width, + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: AColors.black), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + boxShadow: const [AppStyle.boxShadow]), + child: AbsorbPointer( + absorbing: _unpaint, + child: Signature( + controller: _controller, + height: 160 * AppStyle.getScaleFactor(context), + backgroundColor: Colors.transparent, ), - Row( - children: [ - IconButton(onPressed: (){_controller.clear();}, icon: const Icon(Icons.clear)), - IconButton(onPressed: (){_controller.undo();}, icon: const Icon(Icons.undo)), - IconButton(onPressed: (){_controller.redo();}, icon: const Icon(Icons.redo)), - - IconButton(onPressed: (){ + ), + ), + Row( + children: [ + IconButton( + onPressed: () { + _controller.clear(); + }, + icon: const Icon(Icons.clear)), + IconButton( + onPressed: () { + _controller.undo(); + }, + icon: const Icon(Icons.undo)), + IconButton( + onPressed: () { + _controller.redo(); + }, + icon: const Icon(Icons.redo)), + IconButton( + onPressed: () { _unpaint = !_unpaint; setState(() {}); - }, icon: Icon( + }, + icon: Icon( _unpaint ? Icons.draw : Icons.ac_unit, - color: _unpaint ? AColors.orange : null,)), - const Spacer(), - IconButton(onPressed: () async { + color: _unpaint ? AColors.orange : null, + )), + const Spacer(), + IconButton( + onPressed: () async { signature = await _controller.toPngBytes(); + if (widget.onChange != null) { + widget.onChange(signature); + } setState(() {}); - }, icon: const Icon(Icons.check)), - ], - ) + }, + icon: const Icon(Icons.check)), ], - ); - } - ), + ) + ], + ); + }), ], ); } diff --git a/lib/views/widgets/equipment/auto_complete_devices_field.dart b/lib/views/widgets/equipment/auto_complete_devices_field.dart index 0756bc70..0d45aa6e 100644 --- a/lib/views/widgets/equipment/auto_complete_devices_field.dart +++ b/lib/views/widgets/equipment/auto_complete_devices_field.dart @@ -7,10 +7,12 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/device/device.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; + class AutoCompleteDeviceField extends StatefulWidget { final Device initialValue; - final String hospitalId; - final Function(String) onPick; + final int hospitalId; + final Function(int) onPick; const AutoCompleteDeviceField({Key key, this.initialValue, this.onPick, this.hospitalId}) : super(key: key); @@ -19,7 +21,6 @@ class AutoCompleteDeviceField extends StatefulWidget { } class _AutoCompleteDeviceFieldState extends State { - SettingProvider _settingProvider; DevicesProvider _devicesProvider; UserProvider _userProvider; @@ -36,29 +37,31 @@ class _AutoCompleteDeviceFieldState extends State { _controller.dispose(); super.dispose(); } + @override Widget build(BuildContext context) { _settingProvider = Provider.of(context); _userProvider = Provider.of(context); _devicesProvider = Provider.of(context); //Subtitle _subtitle = AppLocalization.of(context).subtitle; - return Container( - padding: const EdgeInsets.symmetric( - horizontal: 16 - ), - decoration: BoxDecoration( - color: Colors.white, - border: Border.all(color:AColors.black), - borderRadius: BorderRadius.circular( - AppStyle.borderRadius * AppStyle.getScaleFactor(context) - ), - boxShadow: [ - AppStyle.boxShadow - ] - ), - child: TypeAheadField( - textFieldConfiguration: TextFieldConfiguration( - style: Theme.of(context).textTheme.headline6, + return LoadingManager( + isLoading: _devicesProvider.isLoading, + isFailedLoading: _devicesProvider.devices == null, + stateCode: _devicesProvider.stateCode, + onRefresh: () async { + _devicesProvider.reset(); + await _devicesProvider.getEquipment(host: _settingProvider.host, user: _userProvider.user, hospitalId: widget.hospitalId); + }, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: AColors.black), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + boxShadow: [AppStyle.boxShadow]), + child: TypeAheadField( + textFieldConfiguration: TextFieldConfiguration( + style: Theme.of(context).textTheme.headline6, controller: _controller, textAlign: TextAlign.center, decoration: const InputDecoration( @@ -68,25 +71,26 @@ class _AutoCompleteDeviceFieldState extends State { enabledBorder: InputBorder.none, ), textInputAction: TextInputAction.search, - ), - suggestionsCallback: (value) async { - return await _devicesProvider.getDevicesList( + ), + suggestionsCallback: (value) async { + return await _devicesProvider.getDevicesList( host: _settingProvider.host, user: _userProvider.user, - hospitalId: widget.hospitalId, + hospitalId: widget.hospitalId ?? _userProvider.user.clientId, serialNumber: value, - ); - }, - itemBuilder: (context, device) { - return ListTile( - title: Text(device.serialNumber), - subtitle: Text(device.model+"/"+device.brand), - ); - }, - onSuggestionSelected: (device) { - _controller.text = device.serialNumber; - widget.onPick(device.id); - }, + ); + }, + itemBuilder: (context, device) { + return ListTile( + title: Text(device.serialNumber), + subtitle: Text("${device.modelDefinition.modelName}/${device.modelDefinition.manufacturerName}"), + ); + }, + onSuggestionSelected: (device) { + _controller.text = device.serialNumber; + widget.onPick(device.id); + }, + ), ), ); } diff --git a/lib/views/widgets/equipment/auto_complete_models_field.dart b/lib/views/widgets/equipment/auto_complete_models_field.dart new file mode 100644 index 00000000..7b2c7555 --- /dev/null +++ b/lib/views/widgets/equipment/auto_complete_models_field.dart @@ -0,0 +1,87 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_typeahead/flutter_typeahead.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/devices_provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/views/app_style/colors.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; + +class AutoCompleteModelField extends StatefulWidget { + final Lookup initialValue; + final Function(Lookup) onPick; + + const AutoCompleteModelField({ + Key key, + this.initialValue, + this.onPick, + }) : super(key: key); + + @override + _AutoCompleteModelFieldState createState() => _AutoCompleteModelFieldState(); +} + +class _AutoCompleteModelFieldState extends State { + SettingProvider _settingProvider; + DevicesProvider _devicesProvider; + UserProvider _userProvider; + TextEditingController _controller; + + @override + void initState() { + _controller = TextEditingController(text: widget.initialValue?.name); + super.initState(); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + _settingProvider = Provider.of(context); + _userProvider = Provider.of(context); + _devicesProvider = Provider.of(context); + //Subtitle _subtitle = AppLocalization.of(context).subtitle; + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: AColors.black), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + boxShadow: [AppStyle.boxShadow]), + child: TypeAheadField( + textFieldConfiguration: TextFieldConfiguration( + style: Theme.of(context).textTheme.headline6, + controller: _controller, + textAlign: TextAlign.center, + decoration: const InputDecoration( + hintText: "Model", + border: InputBorder.none, + disabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + ), + textInputAction: TextInputAction.search, + ), + suggestionsCallback: (value) async { + return await _devicesProvider.getModels( + code: value, + ); + }, + itemBuilder: (context, lookup) { + return ListTile( + title: Text(lookup.name), + ); + }, + onSuggestionSelected: (lookup) { + _controller.text = lookup.name; + widget.onPick(lookup); + }, + ), + ); + } +} diff --git a/lib/views/widgets/equipment/device_button.dart b/lib/views/widgets/equipment/device_button.dart index 571a0b02..8a8b78c0 100644 --- a/lib/views/widgets/equipment/device_button.dart +++ b/lib/views/widgets/equipment/device_button.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/models/device/device.dart'; import 'package:test_sa/models/subtitle.dart'; @@ -27,6 +28,11 @@ class DeviceButton extends StatelessWidget { ), child: Row( children: [ + FaIcon( + FontAwesomeIcons.hardDrive, + size: 28, + color: AColors.black, + ), device == null ? Expanded( child: Padding( @@ -54,14 +60,28 @@ class DeviceButton extends StatelessWidget { color: Theme.of(context).textTheme.subtitle1.color, ), Text( - "${_subtitle.brand} : " + device.brand, + "${_subtitle.assetNumber} : ${device.number}", style: Theme.of(context).textTheme.subtitle2, ), Divider( color: Theme.of(context).textTheme.subtitle1.color, ), Text( - "${_subtitle.model} : " + device.model, + "${_subtitle.assetName} : ${device.modelDefinition.assetName}", + style: Theme.of(context).textTheme.subtitle2, + ), + Divider( + color: Theme.of(context).textTheme.subtitle1.color, + ), + Text( + "${_subtitle.brand} : ${device.modelDefinition.manufacturerName}", + style: Theme.of(context).textTheme.subtitle2, + ), + Divider( + color: Theme.of(context).textTheme.subtitle1.color, + ), + Text( + "${_subtitle.model} : ${device.modelDefinition.modelName}", style: Theme.of(context).textTheme.subtitle2, ), ], diff --git a/lib/views/widgets/equipment/device_item.dart b/lib/views/widgets/equipment/device_item.dart index df07096b..19838675 100644 --- a/lib/views/widgets/equipment/device_item.dart +++ b/lib/views/widgets/equipment/device_item.dart @@ -4,50 +4,56 @@ import 'package:test_sa/models/device/device.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; + class DeviceItem extends StatelessWidget { final Device device; final Function(Device) onPressed; const DeviceItem({Key key, this.device, this.onPressed}) : super(key: key); + @override Widget build(BuildContext context) { Subtitle _subtitle = AppLocalization.of(context).subtitle; return Padding( - padding: EdgeInsets.symmetric(horizontal: 16,vertical: 6), + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 6), child: ElevatedButton( style: ElevatedButton.styleFrom( primary: AColors.primaryColor, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - AppStyle.getBorderRadius(context) - ), + borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), ), ), - - onPressed: (){ + onPressed: () { onPressed(device); }, child: ListTile( - title: Text("${_subtitle.sn} : " + device.serialNumber, - style: Theme.of(context).textTheme.headline6.copyWith( - color: AColors.white - ), - + title: Text( + "${_subtitle.assetName} : \n${device.modelDefinition.assetName}", + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white), ), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Divider(color: Theme.of(context).scaffoldBackgroundColor,), - Text("${_subtitle.brand} : " + device.brand, - style: Theme.of(context).textTheme.subtitle1.copyWith( - color: AColors.white - ), + Divider( + color: Theme.of(context).scaffoldBackgroundColor, + ), + Text( + "${_subtitle.assetNumber} : ${device.number}", + style: Theme.of(context).textTheme.subtitle1.copyWith(color: AColors.white), + ), + Divider( + color: Theme.of(context).scaffoldBackgroundColor, + ), + Text( + "${_subtitle.brand} : ${device.modelDefinition.manufacturerName}", + style: Theme.of(context).textTheme.subtitle1.copyWith(color: AColors.white), + ), + Divider( + color: Theme.of(context).scaffoldBackgroundColor, ), - Divider(color: Theme.of(context).scaffoldBackgroundColor,), - Text("${_subtitle.model} : " + device.model, - style: Theme.of(context).textTheme.subtitle1.copyWith( - color: AColors.white - ), + Text( + "${_subtitle.model} : ${device.modelDefinition.modelName}", + style: Theme.of(context).textTheme.subtitle1.copyWith(color: AColors.white), ), ], ), diff --git a/lib/views/widgets/equipment/single_device_picker.dart b/lib/views/widgets/equipment/single_device_picker.dart index bc8bf527..d8627652 100644 --- a/lib/views/widgets/equipment/single_device_picker.dart +++ b/lib/views/widgets/equipment/single_device_picker.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/devices_provider.dart'; @@ -8,14 +7,17 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/device/device.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/widgets/equipment/device_item.dart'; +import 'package:test_sa/views/widgets/loaders/lazy_loading.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/loaders/no_item_found.dart'; -import 'package:test_sa/views/widgets/qr/scan_qr.dart'; import '../app_text_form_field.dart'; +import '../qr/scan_qr.dart'; + class SingleDevicePicker extends StatefulWidget { static final String id = "/single-device-Picker"; final bool sandraChoice = true; + @override _SingleDevicePickerState createState() => _SingleDevicePickerState(); } @@ -25,30 +27,28 @@ class _SingleDevicePickerState extends State { UserProvider _userProvider; SettingProvider _settingProvider; List _searchableList = []; + List _initList = []; bool _firstTime = true; Subtitle _subtitle; + TextEditingController numberController = TextEditingController(); + TextEditingController snController = TextEditingController(); + _getDevice(String result) async { - if(result == null) return; - showDialog( - barrierDismissible: false, - context: context, - builder: (dialogContext){ - return const Center(child: CircularProgressIndicator()); - } - ); - List devices = await _devicesProvider.getDevicesListBySN( - host: _settingProvider.host, - user: _userProvider.user, - hospitalId: _userProvider.user.hospital.id, - sn: result - ); - Navigator.of(context).pop(); - if(devices.isEmpty){ - Fluttertoast.showToast(msg: _subtitle.noDeviceFound); - return; - } - Navigator.of(context).pop(devices.first); + print(result); + if (result == null) return; + // List devices = await _devicesProvider.getDevicesListBySN(host: _settingProvider.host, user: _userProvider.user, hospitalId: _userProvider.user.clientId, sn: result); + _devicesProvider.reset(); + await _devicesProvider.getEquipment(user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId, serialNumber: "", number: result); + _searchableList.clear(); + _searchableList.addAll(_devicesProvider.devices); + // Navigator.of(context).pop(); + // Navigator.of(context).pop(); + // if (devices.isEmpty) { + // Fluttertoast.showToast(msg: _subtitle.noDeviceFound); + // return; + // } + // Navigator.of(context).pop(devices.first); } @override @@ -58,6 +58,9 @@ class _SingleDevicePickerState extends State { @override void dispose() { + numberController.dispose(); + snController.dispose(); + _devicesProvider.reset(); super.dispose(); } @@ -67,82 +70,91 @@ class _SingleDevicePickerState extends State { _userProvider = Provider.of(context); _settingProvider = Provider.of(context); - if(_firstTime && _devicesProvider.devices != null){ + if (_firstTime && _devicesProvider.devices != null) { + _searchableList.clear(); _searchableList.addAll(_devicesProvider.devices); - _firstTime = false; + _initList.addAll(_devicesProvider.devices); } _subtitle = AppLocalization.of(context).subtitle; return Scaffold( resizeToAvoidBottomInset: false, - body: LoadingManager( - isLoading: _devicesProvider.isLoading, - stateCode: _devicesProvider.stateCode, - isFailedLoading: _devicesProvider.devices == null, - onRefresh: () async { - _devicesProvider.reset(); - await _devicesProvider.getEquipment( - user: _userProvider.user, - host: _settingProvider.host, - hospitalId: _userProvider.user.hospital.id - ); - }, - child: Column( - children: [ - const SizedBox(height: 48), - Padding( - padding: const EdgeInsets.symmetric(vertical: 8,horizontal: 16), - child: Column( - children: [ - ATextFormField( - hintText: _subtitle.searchBySn, - style: Theme.of(context).textTheme.subtitle1, - suffixIcon: const Icon(Icons.search_rounded), - onChange: (value){ - _searchableList.clear(); - _searchableList.addAll(_devicesProvider.devices.where( - (element) => element.serialNumber.toLowerCase().contains( - value.toLowerCase() - ) - ).toList()); - setState(() {}); - }, - ), - const SizedBox(height: 8,), - ATextFormField( - hintText: "Search by Number", - style: Theme.of(context).textTheme.subtitle1, - suffixIcon: const Icon(Icons.search_rounded), - onChange: (value){ - _searchableList.clear(); - _searchableList.addAll(_devicesProvider.devices.where( - (element) => element.number.toLowerCase().contains( - value.toLowerCase() - ) - ).toList()); - setState(() {}); - }, - ), - ], - ), - ), - Expanded( - child: _searchableList.isEmpty ? - NoItemFound(message: _subtitle.noDeviceFound,): - ListView.builder( - padding: EdgeInsets.zero, - shrinkWrap: true, - itemCount: _searchableList.length, - itemBuilder: (listContext,itemIndex){ - return DeviceItem( - device: _searchableList[itemIndex], - onPressed: (device){ - Navigator.of(context).pop(device); - }, - ); - }, + body: SafeArea( + child: LoadingManager( + isLoading: _devicesProvider.isLoading, + stateCode: _devicesProvider.stateCode, + isFailedLoading: _devicesProvider.devices == null, + onRefresh: () async { + _devicesProvider.reset(); + await _devicesProvider.getEquipment(user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId); + }, + child: Column( + children: [ + const SizedBox(height: 16), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), + child: Column( + children: [ + ATextFormField( + hintText: "Search by Asset Number", + controller: numberController, + style: Theme.of(context).textTheme.subtitle1, + suffixIcon: const Icon(Icons.search_rounded), + textInputAction: TextInputAction.search, + onAction: () async { + _devicesProvider.reset(); + await _devicesProvider.getEquipment( + user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId, serialNumber: snController.text, number: numberController.text); + _searchableList.clear(); + _searchableList.addAll(_devicesProvider.devices); + }, + ), + const SizedBox( + height: 8, + ), + ATextFormField( + hintText: _subtitle.searchBySn, + controller: snController, + style: Theme.of(context).textTheme.subtitle1, + suffixIcon: const Icon(Icons.search_rounded), + textInputAction: TextInputAction.search, + onAction: () async { + _devicesProvider.reset(); + await _devicesProvider.getEquipment( + user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId, serialNumber: snController.text, number: numberController.text); + _searchableList.clear(); + _searchableList.addAll(_devicesProvider.devices); + }, + ), + ], + ), ), - ), - ], + Expanded( + child: _searchableList.isEmpty + ? NoItemFound( + message: _subtitle.noDeviceFound, + ) + : LazyLoading( + nextPage: _devicesProvider.nextPage, + onLazyLoad: () async { + await _devicesProvider.getDevicesList( + user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId, serialNumber: snController.text, number: numberController.text); + }, + child: ListView.builder( + padding: EdgeInsets.zero, + shrinkWrap: true, + itemCount: _searchableList.length, + itemBuilder: (listContext, itemIndex) { + return DeviceItem( + device: _searchableList[itemIndex], + onPressed: (device) { + Navigator.of(context).pop(device); + }, + ); + }, + ), + )), + ], + ), ), ), floatingActionButton: FloatingActionButton( @@ -150,7 +162,7 @@ class _SingleDevicePickerState extends State { child: const Icon(Icons.qr_code_scanner), onPressed: () async { String result = await Navigator.of(context).push( - MaterialPageRoute(builder: (_)=> const ScanQr()), + MaterialPageRoute(builder: (_) => const ScanQr()), ) as String; _getDevice(result); }, diff --git a/lib/views/widgets/gas_refill/building_type_menu.dart b/lib/views/widgets/gas_refill/building_type_menu.dart new file mode 100644 index 00000000..7509fe4d --- /dev/null +++ b/lib/views/widgets/gas_refill/building_type_menu.dart @@ -0,0 +1,108 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/models/hospital.dart'; +import 'package:test_sa/views/app_style/colors.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; + +import '../loaders/app_loading.dart'; + +class BuildingTypeMenu extends StatefulWidget { + final Function(Buildings) onSelect; + Buildings initialValue; + List building; + bool enabled; + + BuildingTypeMenu({Key key, this.onSelect, this.initialValue, this.building = const [], this.enabled = true}) : super(key: key); + + @override + _BuildingTypeMenuState createState() { + return _BuildingTypeMenuState(); + } +} + +class _BuildingTypeMenuState extends State { + Buildings _selectedBuilding; + List _building; + + @override + void initState() { + super.initState(); + _selectedBuilding = widget.initialValue; + _building = widget.building; + } + + @override + void didUpdateWidget(covariant BuildingTypeMenu oldWidget) { + if (oldWidget.building != widget.building) { + _building = widget.building; + _selectedBuilding = null; + } + if (oldWidget.initialValue != widget.initialValue && widget.initialValue != null) { + _selectedBuilding = widget.initialValue; + } + super.didUpdateWidget(oldWidget); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: AColors.inputFieldBackgroundColor, + border: Border.all( + color: const Color(0xffefefef), + ), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + // boxShadow: const [ + // AppStyle.boxShadow + // ] + ), + child: widget.enabled + ? DropdownButton( + value: _selectedBuilding, + iconSize: 24, + icon: const Icon(Icons.keyboard_arrow_down_rounded), + elevation: 0, + isExpanded: true, + hint: Text( + "Select Building", + style: Theme.of(context).textTheme.subtitle1, + ), + style: TextStyle(color: Theme.of(context).primaryColor), + underline: const SizedBox.shrink(), + onChanged: (Buildings newValue) { + setState(() { + _selectedBuilding = newValue; + }); + widget.onSelect(newValue); + }, + items: _building?.map>((Buildings value) { + return DropdownMenuItem( + value: value, + child: Text( + value.name ?? "", + style: Theme.of(context).textTheme.subtitle1.copyWith( + color: Theme.of(context).primaryColor, + fontSize: 11, + //fontWeight: FontWeight.bold + ), + ), + ); + })?.toList() ?? + [], + ) + : widget.initialValue == null + ? const Padding( + padding: EdgeInsets.all(8.0), + child: ALoading(), + ) + : ListTile( + title: Center(child: Text(widget.initialValue.name)), + ), + ); + } +} diff --git a/lib/views/widgets/gas_refill/department_type_menu.dart b/lib/views/widgets/gas_refill/department_type_menu.dart new file mode 100644 index 00000000..bd887c74 --- /dev/null +++ b/lib/views/widgets/gas_refill/department_type_menu.dart @@ -0,0 +1,109 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/models/hospital.dart'; +import 'package:test_sa/views/app_style/colors.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; + +import '../loaders/app_loading.dart'; + +class DepartmentTypeMenu extends StatefulWidget { + final Function(Departments) onSelect; + Departments initialValue; + List departments; + bool enabled; + + DepartmentTypeMenu({ + Key key, + this.onSelect, + this.initialValue, + this.departments = const [], + this.enabled = true, + }) : super(key: key); + + @override + _DepartmentTypeMenuState createState() { + return _DepartmentTypeMenuState(); + } +} + +class _DepartmentTypeMenuState extends State { + Departments _selected; + List _departments; + + @override + void initState() { + super.initState(); + _selected = widget.initialValue; + _departments = widget.departments; + } + + @override + void didUpdateWidget(covariant DepartmentTypeMenu oldWidget) { + if (oldWidget.departments != widget.departments) { + _departments = widget.departments; + _selected = null; + } + if (oldWidget.initialValue != widget.initialValue && widget.initialValue != null) { + _selected = widget.initialValue; + } + super.didUpdateWidget(oldWidget); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: AColors.inputFieldBackgroundColor, + border: Border.all( + color: Color(0xffefefef), + ), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + // boxShadow: const [ + // AppStyle.boxShadow + // ] + ), + child: widget.enabled + ? DropdownButton( + value: _selected, + iconSize: 24, + icon: const Icon(Icons.keyboard_arrow_down_rounded), + elevation: 0, + isExpanded: true, + hint: Text( + "Select Department", + style: Theme.of(context).textTheme.subtitle1, + ), + style: TextStyle(color: Theme.of(context).primaryColor), + underline: SizedBox.shrink(), + onChanged: (Departments newValue) { + setState(() { + _selected = newValue; + }); + widget.onSelect(newValue); + }, + items: widget?.departments?.map>((Departments value) { + return DropdownMenuItem( + value: value, + child: Text( + value.name, + style: Theme.of(context).textTheme.subtitle1.copyWith( + color: Theme.of(context).primaryColor, + fontSize: 11, + //fontWeight: FontWeight.bold + ), + ), + ); + })?.toList() ?? + [], + ) + : widget.initialValue == null + ? const Padding(padding: EdgeInsets.all(8.0), child: ALoading()) + : ListTile(title: Center(child: Text(widget.initialValue.name))), + ); + } +} diff --git a/lib/views/widgets/gas_refill/floor_type_menu.dart b/lib/views/widgets/gas_refill/floor_type_menu.dart new file mode 100644 index 00000000..5c29fac1 --- /dev/null +++ b/lib/views/widgets/gas_refill/floor_type_menu.dart @@ -0,0 +1,114 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/models/hospital.dart'; +import 'package:test_sa/views/app_style/colors.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; + +import '../loaders/app_loading.dart'; + +class FloorTypeMenu extends StatefulWidget { + final Function(Floors) onSelect; + Floors initialValue; + List floors; + bool enabled; + + FloorTypeMenu({ + Key key, + this.onSelect, + this.initialValue, + this.floors = const [], + this.enabled = true, + }) : super(key: key); + + @override + _FloorTypeMenuState createState() { + return _FloorTypeMenuState(); + } +} + +class _FloorTypeMenuState extends State { + Floors _selected; + List _floors; + + @override + void initState() { + super.initState(); + _selected = widget.initialValue; + _floors = widget.floors; + } + + @override + void didUpdateWidget(covariant FloorTypeMenu oldWidget) { + if (oldWidget.floors != widget.floors) { + _floors = widget.floors; + _selected = null; + } + if (oldWidget.initialValue != widget.initialValue && widget.initialValue != null) { + _selected = widget.initialValue; + } + super.didUpdateWidget(oldWidget); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: AColors.inputFieldBackgroundColor, + border: Border.all( + color: const Color(0xffefefef), + ), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + // boxShadow: const [ + // AppStyle.boxShadow + // ] + ), + child: widget.enabled + ? DropdownButton( + value: _selected, + iconSize: 24, + icon: const Icon(Icons.keyboard_arrow_down_rounded), + elevation: 0, + isExpanded: true, + hint: Text( + "Select Floor", + style: Theme.of(context).textTheme.subtitle1, + ), + style: TextStyle(color: Theme.of(context).primaryColor), + underline: const SizedBox.shrink(), + onChanged: (Floors newValue) { + setState(() { + _selected = newValue; + }); + widget.onSelect(newValue); + }, + items: _floors?.map>((Floors value) { + return DropdownMenuItem( + value: value, + child: Text( + value.name ?? "", + style: Theme.of(context).textTheme.subtitle1.copyWith( + color: Theme.of(context).primaryColor, + fontSize: 11, + //fontWeight: FontWeight.bold + ), + ), + ); + })?.toList() ?? + [], + ) + : widget.initialValue == null + ? const Padding( + padding: EdgeInsets.all(8.0), + child: ALoading(), + ) + : ListTile( + title: Center(child: Text(widget.initialValue.name)), + ), + ); + } +} diff --git a/lib/views/widgets/gas_refill/gas_refill_create_details_item.dart b/lib/views/widgets/gas_refill/gas_refill_create_details_item.dart index d246d05d..3d913f65 100644 --- a/lib/views/widgets/gas_refill/gas_refill_create_details_item.dart +++ b/lib/views/widgets/gas_refill/gas_refill_create_details_item.dart @@ -1,42 +1,92 @@ import 'package:flutter/material.dart'; import 'package:test_sa/models/gas_refill/gas_refill_details.dart'; import 'package:test_sa/views/app_style/colors.dart'; -class GasRefillCreateDetailsItem extends StatelessWidget { +import 'package:test_sa/views/widgets/app_text_form_field.dart'; +import '../../../controllers/localization/localization.dart'; +import '../buttons/app_button.dart'; +import '../titles/app_sub_title.dart'; + +class GasRefillCreateDetailsItem extends StatefulWidget { final GasRefillDetails model; - final VoidCallback onDelete; + final VoidCallback onPressed; + final bool isUpdate; + + const GasRefillCreateDetailsItem({Key key, this.isUpdate, this.model, this.onPressed}) : super(key: key); + + @override + State createState() => _GasRefillCreateDetailsItemState(); +} + +class _GasRefillCreateDetailsItemState extends State { + GlobalKey _formKey; - const GasRefillCreateDetailsItem({Key key, this.model, this.onDelete}) : super(key: key); + @override + void initState() { + super.initState(); + _formKey = GlobalKey(); + } @override Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Expanded(child: Text(model.type.label)), - IconButton( - onPressed: onDelete, - color: AColors.red, - icon: const Icon(Icons.delete) - ) - ], - ), - Row( - children: [ - Text(model.requestedQuantity.toStringAsFixed(0)), - ], - ), - if(model.deliveredQuantity != null) - Row( - children: [ - const Text("Delivered Quantity"), - Text(model.deliveredQuantity.toStringAsFixed(0)), - ], - ), - const Divider(), - ], + final subtitle = AppLocalization.of(context).subtitle; + final startEditing = widget.isUpdate && (widget.model.selectedForEditing ?? false); + return Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded(child: Text(widget.model.type.name)), + IconButton(onPressed: widget.onPressed, color: widget.isUpdate ? AColors.cyan : AColors.red, icon: Icon(widget.isUpdate ? Icons.edit : Icons.delete)) + ], + ), + Wrap( + spacing: 10, + children: [ + Text("Quantity: ${widget.model.requestedQuantity.toStringAsFixed(0)}"), + Text("Cylinder Size: ${widget.model.cylinderSize.name}"), + Text("Cylinder Type: ${widget.model.cylinderType.name}"), + ], + ), + if (widget.model.deliveredQuantity != null) + Row( + children: [ + const Text("Delivered Quantity: "), + Text(widget.model.deliveredQuantity.toStringAsFixed(0)), + ], + ), + if (startEditing) const SizedBox(height: 16), + if (startEditing) ASubTitle(subtitle.deliveredQuantity), + if (startEditing) const SizedBox(height: 4), + if (startEditing) + ATextFormField( + initialValue: widget.model.deliveredQuantity?.toString() ?? "0", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleMedium, + // validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only", + textInputType: TextInputType.number, + onSaved: (value) { + if (value.isNotEmpty) { + widget.model.deliveredQuantity = double.tryParse(value); + } else { + widget.model.deliveredQuantity = 0; + } + }, + ), + if (startEditing) const SizedBox(height: 8), + if (startEditing) + AButton( + text: subtitle.edit, + onPressed: () { + _formKey.currentState?.save(); + widget.onPressed(); + }, + ), + const Divider(), + ], + ), ); } } diff --git a/lib/views/widgets/gas_refill/gas_refill_item.dart b/lib/views/widgets/gas_refill/gas_refill_item.dart index e9bf3d02..17b2f38a 100644 --- a/lib/views/widgets/gas_refill/gas_refill_item.dart +++ b/lib/views/widgets/gas_refill/gas_refill_item.dart @@ -1,51 +1,36 @@ +import 'package:flutter/material.dart'; import 'package:test_sa/controllers/localization/localization.dart'; -import 'package:test_sa/controllers/providers/api/user_provider.dart'; -import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/gas_refill/gas_refill_model.dart'; -import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/models/subtitle.dart'; -import 'package:test_sa/models/user.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; -import 'package:test_sa/views/pages/user/requests/report/create_service_report.dart'; -import 'package:test_sa/views/pages/user/requests/report/future_service_report.dart'; -import 'package:test_sa/views/widgets/loaders/image_loader.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; + class GasRefillItem extends StatelessWidget { final int index; final GasRefillModel item; final Function(GasRefillModel) onPressed; + const GasRefillItem({Key key, this.item, this.onPressed, this.index}) : super(key: key); @override Widget build(BuildContext context) { - Subtitle _subtitle = AppLocalization.of(context).subtitle; - User _user = Provider.of(context,listen: false).user; - Color itemColor = index % 2 == 0 - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onPrimary; - Color onItemColor = index % 2 != 0 - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onPrimary; + Subtitle subtitle = AppLocalization.of(context).subtitle; + Color itemColor = index % 2 == 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; + Color onItemColor = index % 2 != 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: ElevatedButton( - style: ElevatedButton.styleFrom( - padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8), - backgroundColor: itemColor, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - AppStyle.getBorderRadius(context) - ), - ), - ), + style: ElevatedButton.styleFrom( + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 8), + backgroundColor: itemColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), + ), + ), //padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8), - onPressed: (){ + onPressed: () { onPressed(item); }, child: Column( @@ -59,53 +44,66 @@ class GasRefillItem extends StatelessWidget { children: [ Text( item.title ?? "-----", - style: Theme.of(context).textTheme.headline6.copyWith( - color: onItemColor, - fontSize: 16, - fontWeight: FontWeight.bold - ), + style: Theme.of(context).textTheme.titleLarge.copyWith(color: onItemColor, fontSize: 16, fontWeight: FontWeight.bold), ), Row( children: [ Expanded( child: Text( - _subtitle.hospital, - style: Theme.of(context).textTheme.subtitle2.copyWith( - color: onItemColor, - ), + subtitle.hospital, + style: Theme.of(context).textTheme.titleSmall.copyWith( + color: onItemColor, + ), ), ), - Text( - item.clientName, - style: Theme.of(context).textTheme.subtitle2.copyWith( - color: onItemColor, + if (item.clientName != null) + Text( + item.clientName, + style: Theme.of(context).textTheme.titleSmall.copyWith( + color: onItemColor, + ), ), - ), - ], ), - Divider(color: onItemColor,), + Divider(color: onItemColor), Row( children: [ Expanded( - child: Text( - _subtitle.status, - style: Theme.of(context).textTheme.subtitle2.copyWith( - color: onItemColor, - ), - ), - ), - StatusLabel(label: item.status.label, - color: AColors.getGasStatusColor(item.status.id) + child: Text(subtitle.status, style: Theme.of(context).textTheme.titleSmall.copyWith(color: onItemColor)), ), + if (item.status?.id != null) StatusLabel(label: item.status.name, color: AColors.getGasStatusColor(item.status.id)), + ], + ), + if (item?.expectedDate != null) Divider(color: onItemColor), + if (item?.expectedDate != null) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("Expected Date", style: Theme.of(context).textTheme.titleSmall.copyWith(color: onItemColor)), + Text(item.expectedDate.toIso8601String().split("T").first, style: Theme.of(context).textTheme.titleSmall.copyWith(color: onItemColor)), + ], + ), + if (item?.details?.isNotEmpty ?? false) Divider(color: onItemColor), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (item?.details?.isNotEmpty ?? false) Text("Gas Type", style: Theme.of(context).textTheme.titleSmall.copyWith(color: onItemColor)), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: item.details + .map( + (gas) => gas?.type?.name?.isNotEmpty ?? false + ? Text(gas?.type?.name, style: Theme.of(context).textTheme.titleSmall.copyWith(color: onItemColor)) + : const SizedBox.shrink(), + ) + .toList(), + ) ], ), - //Divider(color: onItemColor,), - ], ), ), - ], ), ], diff --git a/lib/views/widgets/gas_refill/gas_refill_list.dart b/lib/views/widgets/gas_refill/gas_refill_list.dart index e25797d2..b6f58e83 100644 --- a/lib/views/widgets/gas_refill/gas_refill_list.dart +++ b/lib/views/widgets/gas_refill/gas_refill_list.dart @@ -6,6 +6,7 @@ import 'package:test_sa/views/pages/user/gas_refill/gas_refill_details.dart'; import 'package:test_sa/views/widgets/gas_refill/gas_refill_item.dart'; import 'package:test_sa/views/widgets/loaders/lazy_loading.dart'; import 'package:test_sa/views/widgets/loaders/no_item_found.dart'; + class GasRefillList extends StatelessWidget { final List items; final bool nextPage; @@ -15,32 +16,31 @@ class GasRefillList extends StatelessWidget { @override Widget build(BuildContext context) { - - if(items.length == 0){ + if (items.length == 0) { Subtitle subtitle = AppLocalization.of(context).subtitle; - return NoItemFound(message: subtitle.noServiceRequestFound,); + return NoItemFound( + message: subtitle.noServiceRequestFound, + ); } return LazyLoading( nextPage: nextPage, onLazyLoad: onLazyLoad, child: ListView.builder( - //physics: const BouncingScrollPhysics(), - itemCount: items.length, - padding: const EdgeInsets.symmetric(horizontal: 16,vertical: 8), - itemBuilder: (context,itemIndex){ + //physics: const BouncingScrollPhysics(), + itemCount: items.length, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + itemBuilder: (context, itemIndex) { return GasRefillItem( index: itemIndex, item: items[itemIndex], - onPressed: (model){ - Navigator.of(context).push( - MaterialPageRoute( - builder: (_)=> GasRefillDetails(model: model,) - ) - ); + onPressed: (model) { + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => GasRefillDetails( + model: model, + ))); }, ); - } - ), + }), ); } } diff --git a/lib/views/widgets/gas_refill/gas_refill_update_details_item.dart b/lib/views/widgets/gas_refill/gas_refill_update_details_item.dart index 0ccd9e45..d71b2612 100644 --- a/lib/views/widgets/gas_refill/gas_refill_update_details_item.dart +++ b/lib/views/widgets/gas_refill/gas_refill_update_details_item.dart @@ -7,8 +7,8 @@ import 'package:test_sa/views/widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/requests/info_row.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; import 'package:test_sa/views/widgets/titles/app_title.dart'; -class GasRefillUpdateDetailsItem extends StatelessWidget { +class GasRefillUpdateDetailsItem extends StatelessWidget { final GasRefillDetails details; final bool enableEdit; final bool validate; @@ -21,41 +21,44 @@ class GasRefillUpdateDetailsItem extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - ATitle(details.type.label), + ATitle(details.type.name), RequestInfoRow( - title: "Cylinder Size", - info: details.cylinderSize.label, + title: "Cylinder Size", + info: details.cylinderSize.name, ), RequestInfoRow( - title: "Requested Quantity", + title: "Requested Quantity", info: details.requestedQuantity.toStringAsFixed(0), ), - enableEdit ? - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ASubTitle(subtitle.quantity), - if(validate && details.deliveredQuantity == null) - ASubTitle(subtitle.requiredWord,color: Colors.red,), - SizedBox(height: 4,), - ATextFormField( - initialValue: (details.deliveredQuantity ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - validator: (value) => - Validator.isNumeric(value) - ? null : "allow numbers only", - textInputType: TextInputType.number, - onSaved: (value){ - details.deliveredQuantity = int.tryParse(value); - }, - ), - ], - ): - RequestInfoRow( - title: "Delivered Quantity", - info: details.deliveredQuantity.toStringAsFixed(0), - ), + enableEdit + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ASubTitle(subtitle.quantity), + if (validate && details.deliveredQuantity == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + SizedBox( + height: 4, + ), + ATextFormField( + initialValue: (details.deliveredQuantity ?? "").toString(), + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.subtitle1, + validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only", + textInputType: TextInputType.number, + onSaved: (value) { + details.deliveredQuantity = double.tryParse(value); + }, + ), + ], + ) + : RequestInfoRow( + title: "Delivered Quantity", + info: details.deliveredQuantity?.toStringAsFixed(0), + ), //SizedBox(height: 16,) ], ); diff --git a/lib/views/widgets/hospitals/hospital_auto_complete_field.dart b/lib/views/widgets/hospitals/hospital_auto_complete_field.dart index 863ebc08..a8ae2f22 100644 --- a/lib/views/widgets/hospitals/hospital_auto_complete_field.dart +++ b/lib/views/widgets/hospitals/hospital_auto_complete_field.dart @@ -8,14 +8,18 @@ import 'package:test_sa/models/hospital.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; -import 'package:test_sa/views/widgets/hospitals/hospital_item.dart'; class HospitalAutoCompleteField extends StatefulWidget { final String initialValue; - final Function(String) onSearch; - final Function(String) onSave; + final Function(Hospital) onSearch; - const HospitalAutoCompleteField({Key key, this.onSearch, this.initialValue, this.onSave}) : super(key: key); + //final Function(Hospital) onSave; + + const HospitalAutoCompleteField({ + Key key, + this.onSearch, + this.initialValue, + }) : super(key: key); @override _HospitalAutoCompleteFieldState createState() => _HospitalAutoCompleteFieldState(); @@ -31,6 +35,15 @@ class _HospitalAutoCompleteFieldState extends State { super.initState(); } + @override + void didUpdateWidget(covariant HospitalAutoCompleteField oldWidget) { + super.didUpdateWidget(oldWidget); + + if (oldWidget.initialValue != widget.initialValue) { + _controller = TextEditingController(text: widget.initialValue); + } + } + @override void dispose() { _controller.dispose(); @@ -55,31 +68,28 @@ class _HospitalAutoCompleteFieldState extends State { ), child: TypeAheadField( textFieldConfiguration: TextFieldConfiguration( - style: Theme.of(context).textTheme.headline6, - onSubmitted: widget.onSave, - controller: _controller, - textAlign: TextAlign.center, - decoration: InputDecoration( - hintText: _subtitle.hospital, - border: InputBorder.none, - disabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - ), - textInputAction: TextInputAction.search, - onEditingComplete: () { - widget.onSearch(_controller.text); - }), + style: Theme.of(context).textTheme.headline6, + controller: _controller, + textAlign: TextAlign.center, + decoration: InputDecoration( + hintText: _subtitle.hospital, + border: InputBorder.none, + disabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + ), + textInputAction: TextInputAction.search, + ), suggestionsCallback: (vale) async { return await HospitalsProvider().getHospitalsList(host: _settingProvider.host, title: vale); }, itemBuilder: (context, hospital) { - return HospitalItem( - hospital: hospital, + return ListTile( + title: Text(hospital.name), ); }, onSuggestionSelected: (hospital) { - widget.onSearch(hospital.name); + widget.onSearch(hospital); }, ), ); diff --git a/lib/views/widgets/hospitals/hospital_auto_complete_field_new.dart b/lib/views/widgets/hospitals/hospital_auto_complete_field_new.dart new file mode 100644 index 00000000..6ca612a4 --- /dev/null +++ b/lib/views/widgets/hospitals/hospital_auto_complete_field_new.dart @@ -0,0 +1,109 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_typeahead/flutter_typeahead.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/localization/localization.dart'; +import 'package:test_sa/controllers/providers/api/hospitals_provider.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/models/hospital.dart'; +import 'package:test_sa/models/subtitle.dart'; +import 'package:test_sa/views/app_style/colors.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; +import 'package:test_sa/views/widgets/loaders/app_loading.dart'; + +class HospitalAutoCompleteField extends StatefulWidget { + final String initialValue; + final Function(Hospital) onSearch; + final bool enabled; + + //final Function(Hospital) onSave; + + const HospitalAutoCompleteField({ + Key key, + this.onSearch, + this.initialValue, + this.enabled = true, + }) : super(key: key); + + @override + _HospitalAutoCompleteFieldState createState() => _HospitalAutoCompleteFieldState(); +} + +class _HospitalAutoCompleteFieldState extends State { + SettingProvider _settingProvider; + TextEditingController _controller; + + @override + void initState() { + _controller = TextEditingController(text: widget.initialValue); + super.initState(); + } + + @override + void didUpdateWidget(covariant HospitalAutoCompleteField oldWidget) { + super.didUpdateWidget(oldWidget); + + if (oldWidget.initialValue != widget.initialValue) { + _controller = TextEditingController(text: widget.initialValue); + } + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + _settingProvider = Provider.of(context); + Subtitle _subtitle = AppLocalization.of(context).subtitle; + return Container( + padding: EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: AColors.inputFieldBackgroundColor, + border: Border.all( + color: Color(0xffefefef), + ), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + // boxShadow: [ + // AppStyle.boxShadow + // ] + ), + child: widget.enabled + ? TypeAheadField( + textFieldConfiguration: TextFieldConfiguration( + style: Theme.of(context).textTheme.headline6, + controller: _controller, + textAlign: TextAlign.center, + decoration: InputDecoration( + hintText: _subtitle.hospital, + border: InputBorder.none, + disabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + ), + textInputAction: TextInputAction.search, + ), + suggestionsCallback: (vale) async { + return await HospitalsProvider().getHospitalsListByVal(searchVal: _controller.text); + }, + itemBuilder: (context, hospital) { + return ListTile( + title: Text(hospital.name), + ); + }, + onSuggestionSelected: (hospital) { + widget.onSearch(hospital); + }, + ) + : widget.initialValue == null + ? const Padding( + padding: EdgeInsets.all(8.0), + child: ALoading(), + ) + : ListTile( + title: Center(child: Text(widget.initialValue)), + ), + ); + } +} diff --git a/lib/views/widgets/hospitals/hospital_button.dart b/lib/views/widgets/hospitals/hospital_button.dart index 0abefbe4..33ce319c 100644 --- a/lib/views/widgets/hospitals/hospital_button.dart +++ b/lib/views/widgets/hospitals/hospital_button.dart @@ -31,7 +31,7 @@ class HospitalButton extends StatelessWidget { child: Text( hospital?.name ?? _subtitle.pickHospital, style: Theme.of(context).textTheme.bodyText1.copyWith(fontSize: 14, color: AColors.grey3A), - // textScaleFactor: AppStyle.getScaleFactor(context), + // textScaleFactor: AppStyle.getScaleFactor(context), textDirection: TextDirection.rtl, textAlign: TextAlign.left, ), diff --git a/lib/views/widgets/hospitals/hospital_item.dart b/lib/views/widgets/hospitals/hospital_item.dart index 523dace6..bc1a1615 100644 --- a/lib/views/widgets/hospitals/hospital_item.dart +++ b/lib/views/widgets/hospitals/hospital_item.dart @@ -1,38 +1,36 @@ +import 'package:flutter/material.dart'; import 'package:test_sa/models/hospital.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; -import 'package:flutter/material.dart'; + class HospitalItem extends StatelessWidget { final Hospital hospital; final Function(Hospital) onPressed; const HospitalItem({Key key, this.hospital, this.onPressed}) : super(key: key); + @override Widget build(BuildContext context) { return Padding( - padding: const EdgeInsets.symmetric(horizontal: 16,vertical: 6), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: AColors.primaryColor, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - AppStyle.getBorderRadius(context) - ), + borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), ), ), - - onPressed: onPressed == null ? null : (){ - onPressed(hospital); - }, + onPressed: onPressed == null + ? null + : () { + onPressed(hospital); + }, child: ListTile( title: Text( - hospital.name ?? "", - style: Theme.of(context).textTheme.subtitle1.copyWith( - color: AColors.white - ), + hospital.name ?? "", + style: Theme.of(context).textTheme.subtitle1.copyWith(color: AColors.white), textDirection: TextDirection.rtl, ), - ), ), ); diff --git a/lib/views/widgets/hospitals/single_hospital_picker.dart b/lib/views/widgets/hospitals/single_hospital_picker.dart index 27ca0861..afe1f924 100644 --- a/lib/views/widgets/hospitals/single_hospital_picker.dart +++ b/lib/views/widgets/hospitals/single_hospital_picker.dart @@ -10,9 +10,11 @@ import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/loaders/no_item_found.dart'; import '../app_text_form_field.dart'; + class SingleHospitalPicker extends StatefulWidget { static final String id = "/single-Hospital-Picker"; final bool sandraChoice = true; + @override _SingleHospitalPickerState createState() => _SingleHospitalPickerState(); } @@ -22,11 +24,12 @@ class _SingleHospitalPickerState extends State { SettingProvider _settingProvider; List _searchableList = []; bool _firstTime = true; + @override Widget build(BuildContext context) { _hospitalsProvider = Provider.of(context); _settingProvider = Provider.of(context); - if(_firstTime && _hospitalsProvider.hospitals != null){ + if (_firstTime && _hospitalsProvider.hospitals != null) { _searchableList.addAll(_hospitalsProvider.hospitals); _firstTime = false; } @@ -39,44 +42,46 @@ class _SingleHospitalPickerState extends State { isFailedLoading: _hospitalsProvider.hospitals == null, onRefresh: () async { _hospitalsProvider.reset(); - await _hospitalsProvider.getHospitals(host: _settingProvider.host,); + await _hospitalsProvider.getHospitals( + host: _settingProvider.host, + ); }, child: Column( children: [ - SizedBox(height: 48,), + SizedBox( + height: 48, + ), Padding( - padding: const EdgeInsets.symmetric(vertical: 8,horizontal: 16), + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), child: ATextFormField( hintText: _subtitle.searchByName, - style: Theme.of(context).textTheme.headline6, + style: Theme.of(context).textTheme.headline6, suffixIcon: Icon(Icons.search_rounded), - onChange: (value){ + onChange: (value) { _searchableList.clear(); - _searchableList.addAll(_hospitalsProvider.hospitals.where( - (element) => element.name.toLowerCase().contains( - value.toLowerCase() - ) - ).toList()); + _searchableList.addAll(_hospitalsProvider.hospitals.where((element) => element.name.toLowerCase().contains(value.toLowerCase())).toList()); setState(() {}); }, ), ), Expanded( - child: _searchableList.isEmpty ? - NoItemFound(message: _subtitle.noHospitalFound,): - ListView.builder( - padding: EdgeInsets.zero, - shrinkWrap: true, - itemCount: _searchableList.length, - itemBuilder: (listContext,itemIndex){ - return HospitalItem( - hospital: _searchableList[itemIndex], - onPressed: (hospital){ - Navigator.of(context).pop(hospital); - }, - ); - }, - ), + child: _searchableList.isEmpty + ? NoItemFound( + message: _subtitle.noHospitalFound, + ) + : ListView.builder( + padding: EdgeInsets.zero, + shrinkWrap: true, + itemCount: _searchableList.length, + itemBuilder: (listContext, itemIndex) { + return HospitalItem( + hospital: _searchableList[itemIndex], + onPressed: (hospital) { + Navigator.of(context).pop(hospital); + }, + ); + }, + ), ), ], ), diff --git a/lib/views/widgets/images/image_item.dart b/lib/views/widgets/images/image_item.dart index 5e2412a0..5d2dee91 100644 --- a/lib/views/widgets/images/image_item.dart +++ b/lib/views/widgets/images/image_item.dart @@ -3,17 +3,13 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/widgets/loaders/image_loader.dart'; + class ImageItem extends StatelessWidget { final String url; final bool isVideo; final VoidCallback onPressed; - const ImageItem({ - Key key, - this.url, - this.isVideo = false, - this.onPressed - }) : super(key: key); + const ImageItem({Key key, this.url, this.isVideo = false, this.onPressed}) : super(key: key); @override Widget build(BuildContext context) { @@ -24,11 +20,11 @@ class ImageItem extends StatelessWidget { horizontal: 4 * AppStyle.getScaleFactor(context), ), decoration: BoxDecoration( - border: Border.all( - color: Theme.of(context).dividerColor, - width: 2 * AppStyle.getScaleFactor(context), - ), - borderRadius: BorderRadius.circular(8 * AppStyle.getScaleFactor(context)), + border: Border.all( + color: Theme.of(context).dividerColor, + width: 2 * AppStyle.getScaleFactor(context), + ), + borderRadius: BorderRadius.circular(8 * AppStyle.getScaleFactor(context)), ), child: ClipRRect( borderRadius: BorderRadius.circular(6 * AppStyle.getScaleFactor(context)), @@ -36,26 +32,27 @@ class ImageItem extends StatelessWidget { fit: StackFit.expand, alignment: Alignment.center, children: [ - ImageLoader(url: url,), + ImageLoader( + url: url, + ), MaterialButton( onPressed: onPressed, padding: EdgeInsets.zero, child: Visibility( - visible: isVideo, - child: Center( - child: Container( - decoration: BoxDecoration( - color: Colors.black45, - shape: BoxShape.circle, - ), - child: FaIcon( - FontAwesomeIcons.playCircle, - size: 32 * AppStyle.getScaleFactor(context), - color: AColors.orange, + visible: isVideo, + child: Center( + child: Container( + decoration: BoxDecoration( + color: Colors.black45, + shape: BoxShape.circle, + ), + child: FaIcon( + FontAwesomeIcons.playCircle, + size: 32 * AppStyle.getScaleFactor(context), + color: AColors.orange, + ), ), - ), - ) - ), + )), ), ], ), diff --git a/lib/views/widgets/images/images_list.dart b/lib/views/widgets/images/images_list.dart index df2bdb0d..f130f6dd 100644 --- a/lib/views/widgets/images/images_list.dart +++ b/lib/views/widgets/images/images_list.dart @@ -3,6 +3,7 @@ import 'package:test_sa/views/app_style/sizing.dart'; import 'image_item.dart'; import 'images_viewer.dart'; + class ImagesList extends StatelessWidget { final List images; final EdgeInsets padding; @@ -12,22 +13,20 @@ class ImagesList extends StatelessWidget { @override Widget build(BuildContext context) { return ListView.builder( - padding: padding?? EdgeInsets.symmetric(horizontal: 32 * AppStyle.getScaleFactor(context)), - scrollDirection: Axis.horizontal, - itemCount: images.length, - itemBuilder: (context,itemIndex){ - return ImageItem( - url: images[itemIndex], - onPressed: (){ - Navigator.of(context).push( - MaterialPageRoute(builder: (_)=> ImagesViewer( - initialIndex: itemIndex, - images: images, - )) - ); - }, - ); - } - ); + padding: padding ?? EdgeInsets.symmetric(horizontal: 32 * AppStyle.getScaleFactor(context)), + scrollDirection: Axis.horizontal, + itemCount: images.length, + itemBuilder: (context, itemIndex) { + return ImageItem( + url: images[itemIndex], + onPressed: () { + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => ImagesViewer( + initialIndex: itemIndex, + images: images, + ))); + }, + ); + }); } } diff --git a/lib/views/widgets/images/images_viewer.dart b/lib/views/widgets/images/images_viewer.dart index 865f0306..508cf0ca 100644 --- a/lib/views/widgets/images/images_viewer.dart +++ b/lib/views/widgets/images/images_viewer.dart @@ -5,6 +5,7 @@ import 'package:test_sa/views/widgets/loaders/image_loader.dart'; class ImagesViewer extends StatelessWidget { final List images; final int initialIndex; + const ImagesViewer({ Key key, this.images, @@ -20,53 +21,60 @@ class ImagesViewer extends StatelessWidget { child: SafeArea( child: Column( children: [ - images.length == 1 ? SizedBox.shrink() : - Column( - children: [ - SizedBox(height: 8 * AppStyle.getScaleFactor(context),), - TabBar( - isScrollable: images.length * 84 > MediaQuery.of(context).size.width, - indicator: BoxDecoration( - color: Theme.of(context).primaryColor, - borderRadius: BorderRadius.only( - topRight: Radius.circular(24 * AppStyle.getScaleFactor(context)), - bottomLeft: Radius.circular(24 * AppStyle.getScaleFactor(context)), - ), - ), - indicatorSize: TabBarIndicatorSize.label, - tabs: images.map( - (imagePath) => InteractiveViewer( - child: Container( - height: 60, - width: 80, - padding: EdgeInsets.all(AppStyle.getScaleFactor(context),), - child: ClipRRect( - borderRadius: BorderRadius.only( - topRight: Radius.circular(22 * AppStyle.getScaleFactor(context)), - bottomLeft: Radius.circular(22 * AppStyle.getScaleFactor(context)), - ), - child: ImageLoader( - url: imagePath, - boxFit: BoxFit.cover, - ), + images.length == 1 + ? SizedBox.shrink() + : Column( + children: [ + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), + ), + TabBar( + isScrollable: images.length * 84 > MediaQuery.of(context).size.width, + indicator: BoxDecoration( + color: Theme.of(context).primaryColor, + borderRadius: BorderRadius.only( + topRight: Radius.circular(24 * AppStyle.getScaleFactor(context)), + bottomLeft: Radius.circular(24 * AppStyle.getScaleFactor(context)), ), ), - ) - ).toList(), - ), - SizedBox(height: 8 * AppStyle.getScaleFactor(context),), - ], - ), + indicatorSize: TabBarIndicatorSize.label, + tabs: images + .map((imagePath) => InteractiveViewer( + child: Container( + height: 60, + width: 80, + padding: EdgeInsets.all( + AppStyle.getScaleFactor(context), + ), + child: ClipRRect( + borderRadius: BorderRadius.only( + topRight: Radius.circular(22 * AppStyle.getScaleFactor(context)), + bottomLeft: Radius.circular(22 * AppStyle.getScaleFactor(context)), + ), + child: ImageLoader( + url: imagePath, + boxFit: BoxFit.cover, + ), + ), + ), + )) + .toList(), + ), + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), + ), + ], + ), Expanded( child: TabBarView( - children: images.map( - (imagePath) => InteractiveViewer( - child: ImageLoader( - url: imagePath, - boxFit: BoxFit.contain, - ), - ) - ).toList(), + children: images + .map((imagePath) => InteractiveViewer( + child: ImageLoader( + url: imagePath, + boxFit: BoxFit.contain, + ), + )) + .toList(), ), ), ], diff --git a/lib/views/widgets/images/mini_one_image_picker.dart b/lib/views/widgets/images/mini_one_image_picker.dart index 710e960d..26b7f768 100644 --- a/lib/views/widgets/images/mini_one_image_picker.dart +++ b/lib/views/widgets/images/mini_one_image_picker.dart @@ -12,7 +12,8 @@ class AMiniOneImagePicker extends StatefulWidget { final File image; final String label; final bool error; - const AMiniOneImagePicker({Key key, this.label, this.error,this.image, this.onPick}) : super(key: key); + + const AMiniOneImagePicker({Key key, this.label, this.error, this.image, this.onPick}) : super(key: key); @override _AMiniOneImagePickerState createState() => _AMiniOneImagePickerState(); @@ -21,11 +22,13 @@ class AMiniOneImagePicker extends StatefulWidget { class _AMiniOneImagePickerState extends State { File _image; Subtitle _subtitle; + @override void initState() { super.initState(); _image = widget.image; } + @override Widget build(BuildContext context) { _subtitle = AppLocalization.of(context).subtitle; @@ -33,12 +36,14 @@ class _AMiniOneImagePickerState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Visibility( - visible: widget.label != null, + visible: widget.label != null, child: Column( children: [ - SizedBox(height: 8 * AppStyle.getScaleFactor(context),), + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), + ), Text( - widget.label?? '', + widget.label ?? '', style: Theme.of(context).textTheme.headline6, textScaleFactor: AppStyle.getScaleFactor(context), ), @@ -49,32 +54,29 @@ class _AMiniOneImagePickerState extends State { visible: _image == null && widget.error == true, child: Column( children: [ - SizedBox(height: 4,), + SizedBox( + height: 4, + ), Text( _subtitle.requiredImage, - style: Theme.of(context).textTheme.headline6.copyWith( - color: Colors.red - ), + style: Theme.of(context).textTheme.headline6.copyWith(color: Colors.red), textScaleFactor: AppStyle.getScaleFactor(context), ), ], ), ), - SizedBox(height: 8,), + SizedBox( + height: 8, + ), Container( width: MediaQuery.of(context).size.width, child: ElevatedButton( style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - AppStyle.borderRadius * AppStyle.getScaleFactor(context) - ) - ), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context))), //primary: Colors.grey[200], textStyle: Theme.of(context).textTheme.overline, padding: _image == null ? null : EdgeInsets.zero, ), - child: Padding( padding: const EdgeInsets.all(8.0), child: Text( @@ -86,40 +88,30 @@ class _AMiniOneImagePickerState extends State { ImageSource source = await showDialog( context: context, builder: (_) => CupertinoAlertDialog( - actions: [ - TextButton( - child: Text("pick from camera"), - onPressed: () { - Navigator.of(context).pop(ImageSource.camera); - }, - ), - TextButton( - child: Text("pick from gallery"), - onPressed: () { - Navigator.of(context).pop(ImageSource.gallery); - }, - ), - ], - ) - ); - if(source == null) - return; - - final pickedFile = await ImagePicker().pickImage( - source: source, - imageQuality: 70, - maxWidth: 1000, - maxHeight: 1000 - ); + actions: [ + TextButton( + child: Text("pick from camera"), + onPressed: () { + Navigator.of(context).pop(ImageSource.camera); + }, + ), + TextButton( + child: Text("pick from gallery"), + onPressed: () { + Navigator.of(context).pop(ImageSource.gallery); + }, + ), + ], + )); + if (source == null) return; + final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 1000, maxHeight: 1000); setState(() { if (pickedFile != null) { _image = File(pickedFile.path); widget.onPick(_image); - } else { - - } + } else {} }); }, ), @@ -127,4 +119,4 @@ class _AMiniOneImagePickerState extends State { ], ); } -} \ No newline at end of file +} diff --git a/lib/views/widgets/images/multi_image_picker.dart b/lib/views/widgets/images/multi_image_picker.dart index 854209bb..784c42b2 100644 --- a/lib/views/widgets/images/multi_image_picker.dart +++ b/lib/views/widgets/images/multi_image_picker.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:file_picker/file_picker.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; @@ -13,30 +14,31 @@ import 'package:test_sa/views/widgets/buttons/app_flat_button.dart'; import 'multi_image_picker_item.dart'; -class MultiImagesPicker extends StatefulWidget { +class MultiFilesPicker extends StatefulWidget { final String label; final bool error; - final List images; + final List files; + final bool enabled; - const MultiImagesPicker({Key key, this.images, this.label, this.error = false}) : super(key: key); + const MultiFilesPicker({Key key, this.files, this.label, this.error = false, this.enabled = true}) : super(key: key); @override - _MultiImagesPickerState createState() => _MultiImagesPickerState(); + _MultiFilesPickerState createState() => _MultiFilesPickerState(); } -class _MultiImagesPickerState extends State with TickerProviderStateMixin { +class _MultiFilesPickerState extends State with TickerProviderStateMixin { Size _size; @override Widget build(BuildContext context) { _size = MediaQuery.of(context).size; - Subtitle _subtitle = AppLocalization.of(context).subtitle; + Subtitle subtitle = AppLocalization.of(context).subtitle; return Container( - padding: EdgeInsets.all(12), + padding: const EdgeInsets.all(12), decoration: BoxDecoration( - color: Color(0xfff5f5f5), + color: const Color(0xfff5f5f5), border: Border.all( - color: Color(0xffefefef), + color: const Color(0xffefefef), ), borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), ), @@ -48,7 +50,7 @@ class _MultiImagesPickerState extends State with TickerProvid children: [ Expanded( child: Text( - widget.label ?? _subtitle.images, + widget.label ?? subtitle.images, style: Theme.of(context).textTheme.headline6.copyWith( fontSize: 14, ), @@ -56,23 +58,26 @@ class _MultiImagesPickerState extends State with TickerProvid ), ), AFlatButton( - text: _subtitle.add, - onPressed: () { - onImagePick(_subtitle); - }, + text: subtitle.add, + onPressed: widget.enabled + ? () { + // onImagePick(_subtitle); + onFilePicker(subtitle); + } + : null, ), ], ), 12.height, AnimatedSize( - duration: Duration(milliseconds: 400), + duration: const Duration(milliseconds: 400), child: !widget.error - ? SizedBox.shrink() + ? const SizedBox.shrink() : Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - _subtitle.imagesRequired, + subtitle.imagesRequired, style: Theme.of(context).textTheme.headline6.copyWith( fontSize: 14, color: AColors.red, @@ -86,9 +91,9 @@ class _MultiImagesPickerState extends State with TickerProvid ), ), AnimatedSwitcher( - duration: Duration(milliseconds: 400), + duration: const Duration(milliseconds: 400), child: Container( - key: ValueKey(widget.images.length), + key: ValueKey(widget.files.length), width: _size.width, height: 200 * AppStyle.getScaleFactor(context), padding: EdgeInsets.all( @@ -99,14 +104,17 @@ class _MultiImagesPickerState extends State with TickerProvid border: Border.all(color: Theme.of(context).primaryColor, width: 2), borderRadius: BorderRadius.circular(8 * AppStyle.getScaleFactor(context)), ), - child: widget.images.isEmpty + child: widget.files.isEmpty ? MaterialButton( - onPressed: () { - onImagePick(_subtitle); - }, + onPressed: widget.enabled + ? () { + // onImagePick(_subtitle); + onFilePicker(subtitle); + } + : null, child: Center( child: Icon( - Icons.add_a_photo_outlined, + Icons.file_upload, size: 48 * AppStyle.getScaleFactor(context), color: Theme.of(context).primaryColor, )), @@ -117,12 +125,12 @@ class _MultiImagesPickerState extends State with TickerProvid scrollDirection: Axis.horizontal, mainAxisSpacing: 10, crossAxisSpacing: 10, - children: List.generate(widget.images.length, (index) { - File _image = widget.images[index]; - return MultiImagesPickerItem( - image: _image, + children: List.generate(widget.files.length, (index) { + File _image = widget.files[index]; + return MultiFilesPickerItem( + file: _image, onRemoveTap: (image) { - widget.images.remove(image); + widget.files.remove(image); setState(() {}); }, ); @@ -135,9 +143,23 @@ class _MultiImagesPickerState extends State with TickerProvid ); } - onImagePick(Subtitle _subtitle) async { - if (widget.images.length >= 5) { - Fluttertoast.showToast(msg: _subtitle.maxImagesNumberIs5); + onFilePicker(Subtitle subtitle) async { + FilePickerResult result = await FilePicker.platform.pickFiles( + type: FileType.custom, + allowMultiple: true, + allowedExtensions: ['jpg', 'png', 'pdf', 'doc', 'docx', 'xlsx', 'pptx'], + ); + if (result != null) { + for (var path in result.paths) { + widget.files.insert(0, File(path)); + } + setState(() {}); + } + } + + onImagePick(Subtitle subtitle) async { + if (widget.files.length >= 5) { + Fluttertoast.showToast(msg: subtitle.maxImagesNumberIs5); return; } ImageSource source = await showDialog( @@ -145,13 +167,13 @@ class _MultiImagesPickerState extends State with TickerProvid builder: (dialogContext) => CupertinoAlertDialog( actions: [ TextButton( - child: Text(_subtitle.pickFromCamera), + child: Text(subtitle.pickFromCamera), onPressed: () { Navigator.of(dialogContext).pop(ImageSource.camera); }, ), TextButton( - child: Text(_subtitle.pickFromGallery), + child: Text(subtitle.pickFromGallery), onPressed: () { Navigator.of(dialogContext).pop(ImageSource.gallery); }, @@ -163,9 +185,9 @@ class _MultiImagesPickerState extends State with TickerProvid final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800); if (pickedFile != null) { - File _fileImage = File(pickedFile.path); - if (_fileImage != null) { - widget.images.insert(0, _fileImage); + File fileImage = File(pickedFile.path); + if (fileImage != null) { + widget.files.insert(0, fileImage); setState(() {}); } } diff --git a/lib/views/widgets/images/multi_image_picker_item.dart b/lib/views/widgets/images/multi_image_picker_item.dart index be1d1b15..3f1d5805 100644 --- a/lib/views/widgets/images/multi_image_picker_item.dart +++ b/lib/views/widgets/images/multi_image_picker_item.dart @@ -5,70 +5,66 @@ import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; - -class MultiImagesPickerItem extends StatelessWidget { - - final File image; +class MultiFilesPickerItem extends StatelessWidget { + final File file; final Function(File) onRemoveTap; - const MultiImagesPickerItem({Key key, this.image, this.onRemoveTap}) : super(key: key); + const MultiFilesPickerItem({Key key, this.file, this.onRemoveTap}) : super(key: key); @override Widget build(BuildContext context) { + var isImage = file.path.split(".").last.toLowerCase() == "png" || file.path.split(".").last.toLowerCase() == "jpg"; + var isPdf = file.path.split(".").last.toLowerCase() == "pdf"; + var isExcel = file.path.split(".").last.toLowerCase() == "xlsx"; return Container( width: 80 * AppStyle.getScaleFactor(context), height: 80 * AppStyle.getScaleFactor(context), decoration: BoxDecoration( - boxShadow: [ - BoxShadow( - color: Colors.black38, - blurRadius: 2 - ) - ], - image: DecorationImage( - image:FileImage(image), - fit: BoxFit.cover - ), - borderRadius: BorderRadius.circular(8) + boxShadow: [BoxShadow(color: isImage ? Colors.black38 : AColors.cyan.withOpacity(0.5), blurRadius: 2)], + image: DecorationImage( + image: isImage + ? FileImage(file) + : AssetImage("assets/images/${isPdf ? "pdf" : isExcel ? "excel" : "doc"}.png"), + fit: BoxFit.cover, + ), + borderRadius: BorderRadius.circular(8), ), child: MaterialButton( padding: EdgeInsets.zero, - onPressed: (){ - Navigator.of(context).push( + onPressed: () { + if (isImage) { + Navigator.of(context).push( MaterialPageRoute( - builder: (_)=> Scaffold( - body: SafeArea( - child: Stack( - children: [ - Center( - child: InteractiveViewer( - child: Image(image:FileImage(image),) - ), - ), - ABackButton(), - ], - ), + builder: (_) => Scaffold( + body: SafeArea( + child: Stack( + children: [ + Center(child: isImage ? InteractiveViewer(child: Image(image: FileImage(file))) : const SizedBox.shrink()), + const ABackButton(), + ], ), - ) - ) - ); + ), + ), + ), + ); + } }, child: Align( alignment: Alignment.topRight, child: IconButton( - padding: const EdgeInsets.all(2.0), - icon: Container( - padding: EdgeInsets.all(1), - decoration: BoxDecoration( - color: Theme.of(context).scaffoldBackgroundColor.withOpacity(.3), - borderRadius: BorderRadius.circular(8) - ), - child: Icon(Icons.remove_circle,color: AColors.red,) + padding: const EdgeInsets.all(2.0), + icon: Container( + padding: const EdgeInsets.all(1), + decoration: BoxDecoration(color: Theme.of(context).scaffoldBackgroundColor.withOpacity(.3), borderRadius: BorderRadius.circular(8)), + child: const Icon( + Icons.remove_circle, + color: AColors.red, ), - onPressed: (){ - onRemoveTap(image); - }, - ) + ), + onPressed: () { + onRemoveTap(file); + }, + ), ), ), ); diff --git a/lib/views/widgets/images/one_image_picker.dart b/lib/views/widgets/images/one_image_picker.dart index 3ff3ebbf..de5124d0 100644 --- a/lib/views/widgets/images/one_image_picker.dart +++ b/lib/views/widgets/images/one_image_picker.dart @@ -12,7 +12,8 @@ class AOneImagePicker extends StatefulWidget { final File image; final String label; final bool error; - const AOneImagePicker({Key key, this.label, this.error,this.image, this.onPick}) : super(key: key); + + const AOneImagePicker({Key key, this.label, this.error, this.image, this.onPick}) : super(key: key); @override _AOneImagePickerState createState() => _AOneImagePickerState(); @@ -21,11 +22,13 @@ class AOneImagePicker extends StatefulWidget { class _AOneImagePickerState extends State { File _image; Subtitle _subtitle; + @override void initState() { super.initState(); _image = widget.image; } + @override Widget build(BuildContext context) { _subtitle = AppLocalization.of(context).subtitle; @@ -33,12 +36,14 @@ class _AOneImagePickerState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Visibility( - visible: widget.label != null, + visible: widget.label != null, child: Column( children: [ - SizedBox(height: 8 * AppStyle.getScaleFactor(context),), + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), + ), Text( - widget.label?? '', + widget.label ?? '', style: Theme.of(context).textTheme.headline6, textScaleFactor: AppStyle.getScaleFactor(context), ), @@ -49,79 +54,66 @@ class _AOneImagePickerState extends State { visible: _image == null && widget.error == true, child: Column( children: [ - SizedBox(height: 4,), + SizedBox( + height: 4, + ), Text( _subtitle.requiredImage, - style: Theme.of(context).textTheme.headline6.copyWith( - color: Colors.red - ), + style: Theme.of(context).textTheme.headline6.copyWith(color: Colors.red), textScaleFactor: AppStyle.getScaleFactor(context), ), ], ), ), - SizedBox(height: 8,), + SizedBox( + height: 8, + ), Container( height: MediaQuery.of(context).size.height / 8, width: MediaQuery.of(context).size.width, child: ElevatedButton( style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - AppStyle.borderRadius * AppStyle.getScaleFactor(context) - ) - ), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context))), primary: Colors.grey[200], padding: _image == null ? null : EdgeInsets.zero, ), - - child: _image == null ? - Text( - _subtitle.pickImage, - style: Theme.of(context).textTheme.headline6, - textScaleFactor: AppStyle.getScaleFactor(context), - ): - ClipRRect( - borderRadius: BorderRadius.circular( - AppStyle.borderRadius * AppStyle.getScaleFactor(context) - ), - child: Image( - height: MediaQuery.of(context).size.height / 6, - width: MediaQuery.of(context).size.width, - image: FileImage(_image), - fit: BoxFit.cover, - ), - ), + child: _image == null + ? Text( + _subtitle.pickImage, + style: Theme.of(context).textTheme.headline6, + textScaleFactor: AppStyle.getScaleFactor(context), + ) + : ClipRRect( + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + child: Image( + height: MediaQuery.of(context).size.height / 6, + width: MediaQuery.of(context).size.width, + image: FileImage(_image), + fit: BoxFit.cover, + ), + ), onPressed: () async { ImageSource source = await showDialog( context: context, builder: (_) => CupertinoAlertDialog( - actions: [ - TextButton( - child: Text("pick from camera"), - onPressed: () { - Navigator.of(context).pop(ImageSource.camera); - }, - ), - TextButton( - child: Text("pick from gallery"), - onPressed: () { - Navigator.of(context).pop(ImageSource.gallery); - }, - ), - ], - ) - ); - if(source == null) - return; - - final pickedFile = await ImagePicker().pickImage( - source: source, - imageQuality: 70, - maxWidth: 1000, - maxHeight: 1000 - ); + actions: [ + TextButton( + child: Text("pick from camera"), + onPressed: () { + Navigator.of(context).pop(ImageSource.camera); + }, + ), + TextButton( + child: Text("pick from gallery"), + onPressed: () { + Navigator.of(context).pop(ImageSource.gallery); + }, + ), + ], + )); + if (source == null) return; + final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 1000, maxHeight: 1000); setState(() { if (pickedFile != null) { @@ -135,4 +127,4 @@ class _AOneImagePickerState extends State { ], ); } -} \ No newline at end of file +} diff --git a/lib/views/widgets/issues/report_issue_item.dart b/lib/views/widgets/issues/report_issue_item.dart index 8a952be7..8aba4e91 100644 --- a/lib/views/widgets/issues/report_issue_item.dart +++ b/lib/views/widgets/issues/report_issue_item.dart @@ -1,25 +1,21 @@ import 'package:flutter/material.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; + class ReportIssueItem extends StatelessWidget { final bool isSelected; final String issueInfo; - final Function(String,bool) onChange; + final Function(String, bool) onChange; - const ReportIssueItem({ - Key key, - this.isSelected, - this.issueInfo, - this.onChange - }) : super(key: key); + const ReportIssueItem({Key key, this.isSelected, this.issueInfo, this.onChange}) : super(key: key); @override Widget build(BuildContext context) { return MaterialButton( splashColor: AColors.secondaryColor.withOpacity(.5), padding: EdgeInsets.symmetric(vertical: 4), - onPressed: (){ - onChange(issueInfo,!isSelected); + onPressed: () { + onChange(issueInfo, !isSelected); }, child: Column( children: [ @@ -36,14 +32,11 @@ class ReportIssueItem extends StatelessWidget { ), ), Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8 - ), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Checkbox( value: isSelected, - onChanged: (value){ - onChange(issueInfo,value); + onChanged: (value) { + onChange(issueInfo, value); }, ), ), diff --git a/lib/views/widgets/land_page/land_page_item.dart b/lib/views/widgets/land_page/land_page_item.dart index a3085e65..10b7ff05 100644 --- a/lib/views/widgets/land_page/land_page_item.dart +++ b/lib/views/widgets/land_page/land_page_item.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; @@ -6,8 +7,8 @@ class LandPageItem extends StatelessWidget { final String text; final IconData icon; final VoidCallback onPressed; - - const LandPageItem({Key key, this.text, this.icon, this.onPressed}) : super(key: key); + final String svgPath; + const LandPageItem({Key key, this.svgPath, this.text, this.icon, this.onPressed}) : super(key: key); @override Widget build(BuildContext context) { @@ -30,12 +31,20 @@ class LandPageItem extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Icon( - icon, - color: AColors.primaryColor, - size: 42 * AppStyle.getScaleFactor(context), - ), - Text(text, style: TextStyle(color: AColors.grey3A)), + if (icon != null) + Icon( + icon, + color: AColors.primaryColor, + size: 42 * AppStyle.getScaleFactor(context), + ), + if (svgPath != null) + SvgPicture.asset( + svgPath, + width: 42 * AppStyle.getScaleFactor(context), + height: 42 * AppStyle.getScaleFactor(context), + color: AColors.primaryColor, + ), + Text(text, style: const TextStyle(color: AColors.grey3A)), ], ), ), diff --git a/lib/views/widgets/loaders/app_lazy_loading.dart b/lib/views/widgets/loaders/app_lazy_loading.dart index e3378c98..a52417e5 100644 --- a/lib/views/widgets/loaders/app_lazy_loading.dart +++ b/lib/views/widgets/loaders/app_lazy_loading.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'app_loading.dart'; + class ALazyLoading extends StatelessWidget { @override Widget build(BuildContext context) { @@ -10,13 +11,7 @@ class ALazyLoading extends StatelessWidget { height: 36 * AppStyle.getScaleFactor(context), width: 36 * AppStyle.getScaleFactor(context), padding: EdgeInsets.all(8), - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle, - boxShadow: [ - AppStyle.boxShadow - ] - ), + decoration: BoxDecoration(color: Colors.white, shape: BoxShape.circle, boxShadow: [AppStyle.boxShadow]), child: ALoading(), ), ); diff --git a/lib/views/widgets/loaders/app_loading.dart b/lib/views/widgets/loaders/app_loading.dart index 71623050..267313c3 100644 --- a/lib/views/widgets/loaders/app_loading.dart +++ b/lib/views/widgets/loaders/app_loading.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; + class ALoading extends StatelessWidget { const ALoading({Key key}) : super(key: key); diff --git a/lib/views/widgets/loaders/failed_loading.dart b/lib/views/widgets/loaders/failed_loading.dart index 5039628b..b14b45a7 100644 --- a/lib/views/widgets/loaders/failed_loading.dart +++ b/lib/views/widgets/loaders/failed_loading.dart @@ -1,15 +1,12 @@ - import 'package:flutter/material.dart'; import 'package:test_sa/views/app_style/sizing.dart'; + class FailedLoading extends StatelessWidget { final String message; final VoidCallback onReload; - const FailedLoading({ - Key key, - this.message, - this.onReload - }) : super(key: key); + const FailedLoading({Key key, this.message, this.onReload}) : super(key: key); + @override Widget build(BuildContext context) { return Center( @@ -17,11 +14,13 @@ class FailedLoading extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ Text( - message?? "Error Request Failed", + message ?? "Error Request Failed", style: Theme.of(context).textTheme.subtitle1, textScaleFactor: AppStyle.getScaleFactor(context), ), - SizedBox(height: 16,), + SizedBox( + height: 16, + ), OutlinedButton( child: Text("try again"), onPressed: onReload, diff --git a/lib/views/widgets/loaders/image_loader.dart b/lib/views/widgets/loaders/image_loader.dart index 7550de1d..7093d0a3 100644 --- a/lib/views/widgets/loaders/image_loader.dart +++ b/lib/views/widgets/loaders/image_loader.dart @@ -1,17 +1,12 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; + class ImageLoader extends StatelessWidget { final String url; final BoxFit boxFit; final Color color; final Alignment alignment; - const ImageLoader({ - Key key, - @required this.url, - this.boxFit, - this.color, - this.alignment - }) : super(key: key); + const ImageLoader({Key key, @required this.url, this.boxFit, this.color, this.alignment}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/views/widgets/loaders/lazy_loading.dart b/lib/views/widgets/loaders/lazy_loading.dart index d5e5f2ed..04f430c0 100644 --- a/lib/views/widgets/loaders/lazy_loading.dart +++ b/lib/views/widgets/loaders/lazy_loading.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'app_loading.dart'; + class LazyLoading extends StatefulWidget { final Widget child; final bool nextPage; @@ -21,18 +22,15 @@ class LazyLoading extends StatefulWidget { } class _LazyLoadingState extends State with TickerProviderStateMixin { - AnimationController _animationController; Animation _offsetAnimation; _scrollListener() async { if (!_animationController.isAnimating && !_animationController.isCompleted && widget.nextPage) { - _animationController.forward(); - setState(() {}); + //_animationController.forward(); await widget.onLazyLoad(); await Future.delayed(Duration(milliseconds: 600)); - setState(() {}); - _animationController.reverse(); + // _animationController.reverse(); } } @@ -45,13 +43,12 @@ class _LazyLoadingState extends State with TickerProviderStateMixin ); _offsetAnimation = Tween( - begin: const Offset(0.0, .8), + begin: const Offset(0.0, .8), end: const Offset(0, .4), ).animate(CurvedAnimation( parent: _animationController, curve: Curves.easeInOutBack, )); - } @override @@ -66,13 +63,12 @@ class _LazyLoadingState extends State with TickerProviderStateMixin children: [ NotificationListener( onNotification: (notification) { - if(notification.metrics.pixels >= notification.metrics.maxScrollExtent){ + if (notification.metrics.pixels >= notification.metrics.maxScrollExtent) { _scrollListener(); } return false; }, - child: widget.child - ), + child: widget.child), SlideTransition( position: _offsetAnimation, child: Center( @@ -82,13 +78,7 @@ class _LazyLoadingState extends State with TickerProviderStateMixin height: 36 * AppStyle.getScaleFactor(context), width: 36 * AppStyle.getScaleFactor(context), padding: EdgeInsets.all(8), - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle, - boxShadow: [ - AppStyle.boxShadow - ] - ), + decoration: BoxDecoration(color: Colors.white, shape: BoxShape.circle, boxShadow: [AppStyle.boxShadow]), child: ALoading(), ), ), diff --git a/lib/views/widgets/loaders/loading_manager.dart b/lib/views/widgets/loaders/loading_manager.dart index 8ed322e0..7ab67a60 100644 --- a/lib/views/widgets/loaders/loading_manager.dart +++ b/lib/views/widgets/loaders/loading_manager.dart @@ -1,10 +1,11 @@ import 'package:flutter/material.dart'; -import 'package:test_sa/controllers/http_status_manger/http_status_manger.dart'; +import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/models/subtitle.dart'; import 'app_loading.dart'; import 'failed_loading.dart'; + class LoadingManager extends StatefulWidget { final bool isLoading; final bool isFailedLoading; @@ -32,10 +33,9 @@ class LoadingManager extends StatefulWidget { } class _LoadingManagerState extends State { - @override void initState() { - if(widget.onRefresh != null && widget.stateCode == null){ + if (widget.onRefresh != null && widget.stateCode == null) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) { widget.onRefresh(); }); @@ -48,7 +48,7 @@ class _LoadingManagerState extends State { Subtitle subtitle = AppLocalization.of(context).subtitle; Widget placeHolder; // to load data if load not start - if(widget.isLoading == false && widget.stateCode == null){ + if (widget.isLoading != true && widget.stateCode == null) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) { widget.onRefresh(); }); @@ -56,20 +56,19 @@ class _LoadingManagerState extends State { // if loading of still not start in loading (true or null) // return loading widget - if(widget.isLoading != false || widget.stateCode == null){ + if (widget.isLoading != false || widget.stateCode == null) { placeHolder = ALoading(); - }else if(widget.isFailedLoading && !widget.isNotPage){ + } else if (widget.isFailedLoading && !widget.isNotPage) { // if failed return failed widget placeHolder = FailedLoading( - message: HttpStatusManger.getStatusMessage( - status: widget.stateCode, subtitle: subtitle), + message: HttpStatusManger.getStatusMessage(status: widget.stateCode, subtitle: subtitle), onReload: widget.onRefresh, ); } // if load end successfully return loaded widget return RefreshIndicator( - onRefresh: () async{ + onRefresh: () async { await widget.onRefresh(); }, child: AnimatedSwitcher( diff --git a/lib/views/widgets/loaders/no_item_found.dart b/lib/views/widgets/loaders/no_item_found.dart index 5ed637e7..3466f7e7 100644 --- a/lib/views/widgets/loaders/no_item_found.dart +++ b/lib/views/widgets/loaders/no_item_found.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:test_sa/views/app_style/sizing.dart'; + class NoItemFound extends StatelessWidget { final String message; @@ -14,7 +15,7 @@ class NoItemFound extends StatelessWidget { children: [ Center( child: Text( - message ?? "no item found", + message ?? "no item found", style: Theme.of(context).textTheme.headline6, textScaleFactor: AppStyle.getScaleFactor(context), ), diff --git a/lib/views/widgets/notifications/notification_item.dart b/lib/views/widgets/notifications/notification_item.dart index e29cc3c4..6bce172c 100644 --- a/lib/views/widgets/notifications/notification_item.dart +++ b/lib/views/widgets/notifications/notification_item.dart @@ -1,13 +1,13 @@ +import 'package:flutter/material.dart'; import 'package:test_sa/models/app_notification.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; + class NotificationItem extends StatelessWidget { final AppNotification notification; final Function(AppNotification) onPressed; - const NotificationItem({Key key, this.notification, this.onPressed}) : super(key: key); + const NotificationItem({Key key, this.notification, this.onPressed}) : super(key: key); @override Widget build(BuildContext context) { @@ -15,20 +15,16 @@ class NotificationItem extends StatelessWidget { padding: const EdgeInsets.symmetric(vertical: 4), child: ElevatedButton( style: ElevatedButton.styleFrom( - padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8), + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8), primary: AColors.primaryColor, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - AppStyle.getBorderRadius(context) - ), + borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), ), ), - - onPressed: (){ + onPressed: () { onPressed(notification); }, - - child:Column( + child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( @@ -36,30 +32,24 @@ class NotificationItem extends StatelessWidget { Expanded( child: Text( notification.title ?? "No Hospital Found", - style: Theme.of(context).textTheme.headline6.copyWith( - color: AColors.white, - fontSize: 16, - fontWeight: FontWeight.bold - ), + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontSize: 16, fontWeight: FontWeight.bold), ), ), Text( notification.date ?? "complaint not available", - style: Theme.of(context).textTheme.subtitle1.copyWith( - color: AColors.white, - fontSize: 12, - fontWeight: FontWeight.bold - ), + style: Theme.of(context).textTheme.subtitle1.copyWith(color: AColors.white, fontSize: 12, fontWeight: FontWeight.bold), ), ], ), - Divider(color: AColors.white,), + Divider( + color: AColors.white, + ), Text( notification.description ?? "complaint not available", style: Theme.of(context).textTheme.subtitle1.copyWith( - color: AColors.white, - fontSize: 14, - ), + color: AColors.white, + fontSize: 14, + ), ), ], ), diff --git a/lib/views/widgets/parts/auto_complete_parts_field.dart b/lib/views/widgets/parts/auto_complete_parts_field.dart index 9c31d01e..4a537cc7 100644 --- a/lib/views/widgets/parts/auto_complete_parts_field.dart +++ b/lib/views/widgets/parts/auto_complete_parts_field.dart @@ -7,11 +7,11 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/part.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; -import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; + class AutoCompletePartsField extends StatefulWidget { final String initialValue; - final Function(Part) onPick; final bool clearAfterPick; + final Function(Part) onPick; const AutoCompletePartsField({Key key, this.initialValue, this.onPick, this.clearAfterPick = true}) : super(key: key); @@ -20,7 +20,6 @@ class AutoCompletePartsField extends StatefulWidget { } class _AutoCompletePartsFieldState extends State { - SettingProvider _settingProvider; PartsProvider _partsProvider; UserProvider _userProvider; @@ -37,72 +36,54 @@ class _AutoCompletePartsFieldState extends State { _controller.dispose(); super.dispose(); } + @override Widget build(BuildContext context) { _settingProvider = Provider.of(context); _userProvider = Provider.of(context); _partsProvider = Provider.of(context); //Subtitle _subtitle = AppLocalization.of(context).subtitle; - return LoadingManager( - isLoading: _partsProvider.isLoading, - isFailedLoading: _partsProvider.parts == null, - stateCode: _partsProvider.stateCode, - onRefresh: () async { - _partsProvider.reset(); - await _partsProvider.getParts( - host: _settingProvider.host, - user: _userProvider.user, - ); - }, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 16 - ), - decoration: BoxDecoration( - color: Colors.white, - border: Border.all(color:AColors.black), - borderRadius: BorderRadius.circular( - AppStyle.borderRadius * AppStyle.getScaleFactor(context) - ), - boxShadow: const [ - AppStyle.boxShadow - ] - ), - child: TypeAheadField( - textFieldConfiguration: TextFieldConfiguration( - style: Theme.of(context).textTheme.subtitle1, - controller: _controller, - textAlign: TextAlign.center, - decoration: const InputDecoration( - border: InputBorder.none, - disabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - ), - textInputAction: TextInputAction.search, - ), - suggestionsCallback: (vale) async { - return await _partsProvider.getPartsList( - host: _settingProvider.host, - title: vale - ); - }, - itemBuilder: (context, part) { - return ListTile( - title: Text(part.code), - subtitle: Text(part.name, style: Theme.of(context).textTheme.caption,), - ); - }, - onSuggestionSelected: (part) { - if(widget.clearAfterPick){ - _controller.clear(); - } else{ - _controller.text = part.code; - } - widget.onPick(part); - }, + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: AColors.black), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + boxShadow: const [AppStyle.boxShadow]), + child: TypeAheadField( + textFieldConfiguration: TextFieldConfiguration( + style: Theme.of(context).textTheme.subtitle1, + controller: _controller, + textAlign: TextAlign.center, + decoration: const InputDecoration( + border: InputBorder.none, + disabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, ), + textInputAction: TextInputAction.search, ), + suggestionsCallback: (vale) async { + return await _partsProvider.getPartsList(host: _settingProvider.host, title: vale); + }, + itemBuilder: (context, part) { + return ListTile( + title: Text(part.code), + subtitle: Text( + part.name, + style: Theme.of(context).textTheme.caption, + ), + ); + }, + onSuggestionSelected: (part) { + if (widget.clearAfterPick) { + _controller.clear(); + } else { + _controller.text = part.code; + } + widget.onPick(part); + }, + ), ); } } diff --git a/lib/views/widgets/parts/part_item.dart b/lib/views/widgets/parts/part_item.dart index 354e4302..c108d07e 100644 --- a/lib/views/widgets/parts/part_item.dart +++ b/lib/views/widgets/parts/part_item.dart @@ -1,13 +1,14 @@ +import 'package:flutter/material.dart'; import 'package:test_sa/models/part.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/widgets/buttons/app_icon_button2.dart'; -import 'package:flutter/material.dart'; -class PartItem extends StatefulWidget { +class PartItem extends StatefulWidget { final Part part; final Function(Part) onDelete; + final Function(int qty) onEdit; - const PartItem({Key key, this.part, this.onDelete}) : super(key: key); + const PartItem({Key key, this.part, this.onEdit, this.onDelete}) : super(key: key); @override _PartItemState createState() => _PartItemState(); @@ -19,69 +20,80 @@ class _PartItemState extends State { //final _subtitle = AppLocalization.of(context).subtitle; return Column( children: [ - Divider(), + const Divider(), Row( children: [ Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: Text(widget.part.code, - style: Theme.of(context).textTheme.bodyText1.copyWith( - fontSize: 12, - fontWeight: FontWeight.bold + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Text( + widget?.part?.code ?? "", + style: Theme.of(context).textTheme.bodyText1.copyWith(fontSize: 12, fontWeight: FontWeight.bold), ), ), - ), - AIconButton2( - iconData: Icons.add, - color: Theme.of(context).primaryColor, - onPressed: (){ - widget.part.quantity++; - setState(() {}); - }, - ), - AIconButton2( - iconData: Icons.remove, - color: Theme.of(context).primaryColor, - onPressed: widget.part.quantity < 2 ? null : (){ - widget.part.quantity--; - setState(() {}); - }, - ), - SizedBox(width: 8*AppStyle.getScaleFactor(context),), - Text(widget.part.quantity.toString(), - style: Theme.of(context).textTheme.headline6.copyWith( - //fontSize: 12, - //fontWeight: FontWeight.bold + AIconButton2( + iconData: Icons.add, + color: Theme.of(context).primaryColor, + onPressed: () { + if (widget.onEdit == null) { + ++widget.part.quantity; + } else { + widget.onEdit(++widget.part.quantity); + } + setState(() {}); + }, + ), + AIconButton2( + iconData: Icons.remove, + color: Theme.of(context).primaryColor, + onPressed: widget.part.quantity < 2 + ? null + : () { + if (widget.onEdit == null) { + --widget.part.quantity; + } else { + widget.onEdit(--widget.part.quantity); + } + setState(() {}); + }, + ), + SizedBox( + width: 8 * AppStyle.getScaleFactor(context), ), - ), - SizedBox(width: 8*AppStyle.getScaleFactor(context),), - ], - ), - widget.part.name == null ? SizedBox.shrink() : - Text(widget.part.name, - style: Theme.of(context).textTheme.caption.copyWith( - fontSize: 11, - fontWeight: FontWeight.bold + Text( + widget.part.quantity.toString(), + style: Theme.of(context).textTheme.headline6.copyWith( + //fontSize: 12, + //fontWeight: FontWeight.bold + ), + ), + SizedBox( + width: 8 * AppStyle.getScaleFactor(context), + ), + ], ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ], - )), + widget.part.name == null + ? const SizedBox.shrink() + : Text( + widget.part.name, + style: Theme.of(context).textTheme.caption.copyWith(fontSize: 11, fontWeight: FontWeight.bold), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), AIconButton2( iconData: Icons.close, color: Colors.red, - onPressed: (){ + onPressed: () { widget.onDelete(widget.part); }, ), - - ], ), ], diff --git a/lib/views/widgets/pentry/auto_complete_fields/auto_complete_devices_field.dart b/lib/views/widgets/pentry/auto_complete_fields/auto_complete_devices_field.dart index ea2228cd..0691e452 100644 --- a/lib/views/widgets/pentry/auto_complete_fields/auto_complete_devices_field.dart +++ b/lib/views/widgets/pentry/auto_complete_fields/auto_complete_devices_field.dart @@ -8,9 +8,10 @@ import 'package:test_sa/models/device/device.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; + class AutoCompleteDeviceNumberField extends StatefulWidget { final Lookup initialValue; - final String hospitalId; + final int hospitalId; final Function(Lookup) onPick; const AutoCompleteDeviceNumberField({Key key, this.initialValue, this.onPick, this.hospitalId}) : super(key: key); @@ -20,7 +21,6 @@ class AutoCompleteDeviceNumberField extends StatefulWidget { } class _AutoCompleteDeviceNumberFieldState extends State { - SettingProvider _settingProvider; DevicesProvider _devicesProvider; UserProvider _userProvider; @@ -28,7 +28,7 @@ class _AutoCompleteDeviceNumberFieldState extends State(context); @@ -44,49 +45,42 @@ class _AutoCompleteDeviceNumberFieldState extends State(context); //Subtitle _subtitle = AppLocalization.of(context).subtitle; return Container( - padding: const EdgeInsets.symmetric( - horizontal: 16 - ), + padding: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( color: Colors.white, - border: Border.all(color:AColors.black), - borderRadius: BorderRadius.circular( - AppStyle.borderRadius * AppStyle.getScaleFactor(context) - ), - boxShadow: const [ - AppStyle.boxShadow - ] - ), + border: Border.all(color: AColors.black), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + boxShadow: const [AppStyle.boxShadow]), child: TypeAheadField( textFieldConfiguration: TextFieldConfiguration( - style: Theme.of(context).textTheme.headline6, - controller: _controller, - textAlign: TextAlign.center, - decoration: const InputDecoration( - border: InputBorder.none, - disabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - ), - textInputAction: TextInputAction.search, + style: Theme.of(context).textTheme.headline6, + controller: _controller, + textAlign: TextAlign.center, + decoration: const InputDecoration( + border: InputBorder.none, + disabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + ), + textInputAction: TextInputAction.search, ), suggestionsCallback: (vale) async { return await _devicesProvider.getDevicesList( - host: _settingProvider.host, - user: _userProvider.user, - hospitalId: widget.hospitalId, - number: vale, + host: _settingProvider.host, + user: _userProvider.user, + hospitalId: widget.hospitalId, + number: vale, ); }, itemBuilder: (context, device) { return ListTile( title: Text(device.number), - subtitle: Text("${device.model}/${device.brand}"), + subtitle: Text("${device.modelDefinition.modelName}/${device.modelDefinition.manufacturerName}"), ); }, onSuggestionSelected: (device) { _controller.text = device.number; - widget.onPick(Lookup(id: int.tryParse(device.id),label: device.number)); + widget.onPick(Lookup(id: device.id, name: device.number)); }, ), ); diff --git a/lib/views/widgets/pentry/pentry_calibration_tool_form.dart b/lib/views/widgets/pentry/pentry_calibration_tool_form.dart index 70528bb3..27033ba2 100644 --- a/lib/views/widgets/pentry/pentry_calibration_tool_form.dart +++ b/lib/views/widgets/pentry/pentry_calibration_tool_form.dart @@ -9,11 +9,14 @@ import 'package:test_sa/views/widgets/buttons/app_small_button.dart'; import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; import 'package:test_sa/views/widgets/pentry/auto_complete_fields/auto_complete_devices_field.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; + class PentryCalibrationToolForm extends StatefulWidget { final List models; final bool enableValidate; const PentryCalibrationToolForm({ - Key key, this.models, this.enableValidate, + Key key, + this.models, + this.enableValidate, }) : super(key: key); @override @@ -21,75 +24,79 @@ class PentryCalibrationToolForm extends StatefulWidget { } class _PentryCalibrationToolFormState extends State { - - @override Widget build(BuildContext context) { final subtitle = AppLocalization.of(context).subtitle; final userProvider = Provider.of(context); return ListView.builder( - padding: EdgeInsets.only( - top: 12 * AppStyle.getScaleFactor(context), - left: 12 * AppStyle.getScaleFactor(context), - right: 12 * AppStyle.getScaleFactor(context), - bottom: 80 * AppStyle.getScaleFactor(context) - ), - itemCount: widget.models.length + 1, - itemBuilder: (context,index){ - if(index == widget.models.length){ - return AButton( - text: subtitle.add, - onPressed: (){ - widget.models.add(CalibrationTool()); - setState(() {}); - }, - ); - } - final model = widget.models[index]; - return ListView( - shrinkWrap: true, - physics: const ClampingScrollPhysics(), - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ASubTitle("#${index+1}"), - if(index != 0) - ASmallButton( - color: Theme.of(context).colorScheme.error, - text: subtitle.delete, - onPressed: (){ - widget.models.remove(model); - setState(() {}); - }, - ), - ], - ), - const SizedBox(height: 8,), - const ASubTitle("Asset Number"), - const SizedBox(height: 4,), - AutoCompleteDeviceNumberField( - initialValue: model.assetsNumber, - hospitalId: userProvider.user.hospital.id, - onPick: (number){ - model.assetsNumber = number; - }, - ), - const SizedBox(height: 8,), - const ASubTitle("Date of Testing"), - const SizedBox(height: 4,), - ADatePicker( - date: model.dataOfTesting, - onDatePicker: (date){ - model.dataOfTesting =date; + padding: EdgeInsets.only( + top: 12 * AppStyle.getScaleFactor(context), left: 12 * AppStyle.getScaleFactor(context), right: 12 * AppStyle.getScaleFactor(context), bottom: 80 * AppStyle.getScaleFactor(context)), + itemCount: widget.models.length + 1, + itemBuilder: (context, index) { + if (index == widget.models.length) { + return AButton( + text: subtitle.add, + onPressed: () { + widget.models.add(CalibrationTool()); setState(() {}); }, - ), - const SizedBox(height: 8,), - Divider(color: Theme.of(context).textTheme.titleMedium.color,), - ], - ); - } - ); + ); + } + final model = widget.models[index]; + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ASubTitle("#${index + 1}"), + if (index != 0) + ASmallButton( + color: Theme.of(context).colorScheme.error, + text: subtitle.delete, + onPressed: () { + widget.models.remove(model); + setState(() {}); + }, + ), + ], + ), + const SizedBox( + height: 8, + ), + const ASubTitle("Asset Number"), + const SizedBox( + height: 4, + ), + AutoCompleteDeviceNumberField( + initialValue: model.assetsNumber, + hospitalId: userProvider.user.clientId, + onPick: (number) { + model.assetsNumber = number; + }, + ), + const SizedBox( + height: 8, + ), + const ASubTitle("Date of Testing"), + const SizedBox( + height: 4, + ), + ADatePicker( + date: model.dataOfTesting, + onDatePicker: (date) { + model.dataOfTesting = date; + setState(() {}); + }, + ), + const SizedBox( + height: 8, + ), + Divider( + color: Theme.of(context).textTheme.titleMedium.color, + ), + ], + ); + }); } } diff --git a/lib/views/widgets/pentry/pentry_info_form.dart b/lib/views/widgets/pentry/pentry_info_form.dart index 1fadc1c9..577e28e2 100644 --- a/lib/views/widgets/pentry/pentry_info_form.dart +++ b/lib/views/widgets/pentry/pentry_info_form.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/localization/localization.dart'; @@ -6,16 +8,22 @@ import 'package:test_sa/models/pantry/pentry.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; +import 'package:test_sa/views/widgets/e_signature/e_signature.dart'; import 'package:test_sa/views/widgets/images/mini_one_image_picker.dart'; -import 'package:test_sa/views/widgets/status/pentry/pentry_status_mune.dart'; import 'package:test_sa/views/widgets/status/pentry/pentry_visit_status_mune.dart'; import 'package:test_sa/views/widgets/timer/app_timer.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; + +import '../status/pentry/pentry_status_mune.dart'; + class PentryInfoForm extends StatefulWidget { final Pentry model; final bool enableValidate; + const PentryInfoForm({ - Key key, this.model, this.enableValidate, + Key key, + this.model, + this.enableValidate, }) : super(key: key); @override @@ -23,91 +31,174 @@ class PentryInfoForm extends StatefulWidget { } class _PentryInfoFormState extends State { - @override Widget build(BuildContext context) { final subtitle = AppLocalization.of(context).subtitle; final userProvider = Provider.of(context); return ListView( padding: EdgeInsets.only( - top: 12 * AppStyle.getScaleFactor(context), - left: 12 * AppStyle.getScaleFactor(context), - right: 12 * AppStyle.getScaleFactor(context), - bottom: 80 * AppStyle.getScaleFactor(context) - ), + top: 12 * AppStyle.getScaleFactor(context), left: 12 * AppStyle.getScaleFactor(context), right: 12 * AppStyle.getScaleFactor(context), bottom: 80 * AppStyle.getScaleFactor(context)), shrinkWrap: true, physics: const ClampingScrollPhysics(), children: [ - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), const ASubTitle("PPM Visit Status"), - if(widget.enableValidate && widget.model.ppmVisitStatus == null) - ASubTitle(subtitle.requiredWord,color: Colors.red,), - const SizedBox(height: 4,), + if (widget.enableValidate && widget.model.ppmVisitStatus == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), PentryVisitsStatusMenu( initialValue: widget.model.ppmVisitStatus, - onSelect: (status){ + onSelect: (status) { widget.model.ppmVisitStatus = status; }, ), - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), const ASubTitle("Timer"), - if(widget.enableValidate && widget.model?.timer?.endAt == null) - ASubTitle(subtitle.requiredWord,color: Colors.red,), - const SizedBox(height: 4,), + if (widget.enableValidate && widget.model?.timer?.endAt == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), AppTimer( timer: widget.model.timer, - onChange: (timer) async{ + enabled: widget.model.timer.endAt == null, + onChange: (timer) async { widget.model.timer = timer; return true; }, ), - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), const ASubTitle("Status"), - // if(widget.enableValidate && widget.model.status == null) - // ASubTitle(subtitle.requiredWord,color: Colors.red,), - const SizedBox(height: 4,), + if (widget.enableValidate && widget.model.status == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), PentryStatusMenu( initialValue: widget.model.status, - onSelect: (status){ + onSelect: (status) { widget.model.status = status; }, ), - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), const ASubTitle("Actual Visit Date"), - if(widget.enableValidate && widget.model.actualVisitDate == null) - ASubTitle(subtitle.requiredWord,color: Colors.red,), - const SizedBox(height: 4,), + if (widget.enableValidate && widget.model.actualVisitDate == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), ADatePicker( date: widget.model.actualVisitDate, from: DateTime.now().subtract(const Duration(days: 30)), - onDatePicker: (date){ - if(date == null) return; + onDatePicker: (date) { + if (date == null) return; widget.model.actualVisitDate = date; setState(() {}); }, ), - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), + const ASubTitle("Expected Visit Date"), + if (widget.enableValidate && widget.model.expectedVisitDate == null) + ASubTitle( + subtitle.requiredWord, + color: Colors.red, + ), + const SizedBox( + height: 4, + ), + ADatePicker( + date: widget.model.expectedVisitDate, + from: DateTime.now().subtract(const Duration(days: 30)), + onDatePicker: (date) { + if (date == null) return; + widget.model.expectedVisitDate = date; + setState(() {}); + }, + ), + const SizedBox( + height: 8, + ), const ASubTitle("Traveling Hours"), - const SizedBox(height: 4,), + const SizedBox( + height: 4, + ), ATextFormField( initialValue: (widget.model.travelingHours ?? "").toString(), textAlign: TextAlign.center, style: Theme.of(context).textTheme.subtitle1, textInputType: TextInputType.number, - onChange: (value){ + onChange: (value) { widget.model.travelingHours = value; }, ), - const SizedBox(height: 12,), + const SizedBox( + height: 12, + ), const ASubTitle("PPM Attachment"), AMiniOneImagePicker( //error: _validate && _serviceReport.image == null, image: widget.model.imageFile, - onPick: (image){ - widget.model.imageFile =image; + onPick: (image) { + widget.model.imageFile = image; }, ), - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), + const ASubTitle("Nurse Signature"), + ESignature( + oldSignature: widget.model.signatureNurse, + newSignature: widget.model.localNurseSignature, + onChange: (signature) { + if (signature == null || signature.isEmpty) { + return; + } + widget.model.localNurseSignature = signature; + widget.model.signatureNurse = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + }, + ), + const SizedBox( + height: 8, + ), + const ASubTitle("Engineer Signature"), + ESignature( + oldSignature: widget.model.signatureEngineer, + newSignature: widget.model.localNurseSignature, + onChange: (signature) { + if (signature == null || signature.isEmpty) { + return; + } + widget.model.localNurseSignature = signature; + widget.model.signatureEngineer = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + }, + ), + const SizedBox( + height: 8, + ), ], ); } diff --git a/lib/views/widgets/pentry/pentry_pm_kit_form.dart b/lib/views/widgets/pentry/pentry_pm_kit_form.dart index 6fdd3b43..3fb154d7 100644 --- a/lib/views/widgets/pentry/pentry_pm_kit_form.dart +++ b/lib/views/widgets/pentry/pentry_pm_kit_form.dart @@ -3,16 +3,18 @@ import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/pantry/pm_kit.dart'; import 'package:test_sa/views/app_style/sizing.dart'; -import 'package:test_sa/views/widgets/app_text_form_field.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; import 'package:test_sa/views/widgets/buttons/app_small_button.dart'; import 'package:test_sa/views/widgets/parts/auto_complete_parts_field.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; + class PentryPMKitForm extends StatefulWidget { final List models; final bool enableValidate; const PentryPMKitForm({ - Key key, this.models, this.enableValidate, + Key key, + this.models, + this.enableValidate, }) : super(key: key); @override @@ -20,7 +22,6 @@ class PentryPMKitForm extends StatefulWidget { } class _PentryPMKitFormState extends State { - @override Widget build(BuildContext context) { final subtitle = AppLocalization.of(context).subtitle; @@ -29,126 +30,62 @@ class _PentryPMKitFormState extends State { top: 12 * AppStyle.getScaleFactor(context), left: 12 * AppStyle.getScaleFactor(context), right: 12 * AppStyle.getScaleFactor(context), - bottom: 80 * AppStyle.getScaleFactor(context) + bottom: 100 * AppStyle.getScaleFactor(context) + MediaQuery.of(context).padding.bottom, ), - itemCount: widget.models.length + 1, - itemBuilder: (context,index){ - if(index == widget.models.length){ + itemCount: widget.models.length + 1, + shrinkWrap: true, + itemBuilder: (context, index) { + if (index == widget.models.length) { return AButton( text: subtitle.add, - onPressed: (){ + onPressed: () { widget.models.add(PMKit()); setState(() {}); }, ); } final model = widget.models[index]; - return ListView( - shrinkWrap: true, - physics: const ClampingScrollPhysics(), + return Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - ASubTitle("#${index+1}"), - if(index != 0) + ASubTitle("#${index + 1}"), + if (index != 0) ASmallButton( color: Theme.of(context).colorScheme.error, text: subtitle.delete, - onPressed: (){ + onPressed: () { widget.models.remove(model); setState(() {}); }, ), ], ), - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), const ASubTitle("Item Code"), - const SizedBox(height: 4,), + const SizedBox( + height: 4, + ), AutoCompletePartsField( clearAfterPick: false, - initialValue: (model.itemCode?.label ?? "").toString(), - onPick: (part){ - model.itemCode = Lookup(id: int.tryParse(part.id),label: part.code); - }, - ), - const SizedBox(height: 8,), - const ASubTitle("Item Name"), - const SizedBox(height: 4,), - ATextFormField( - initialValue: (model.itemName ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - textInputType: TextInputType.text, - onChange: (value){ - model.itemName = value; - }, - ), - const SizedBox(height: 8,), - const ASubTitle("Preparation Time Frame"), - const SizedBox(height: 4,), - ATextFormField( - initialValue: (model.preparationTimeFrame ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - textInputType: TextInputType.text, - onChange: (value){ - model.preparationTimeFrame = value; - }, - ), - const SizedBox(height: 8,), - const ASubTitle("kit Frequency Demand"), - const SizedBox(height: 4,), - ATextFormField( - initialValue: (model.kitFrequencyDemand ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - textInputType: TextInputType.text, - onChange: (value){ - model.kitFrequencyDemand = value; + initialValue: (model.itemCode?.name ?? "").toString(), + onPick: (part) { + model.itemCode = Lookup(id: part.id, name: part.code); }, ), - const SizedBox(height: 8,), - const ASubTitle("Availability"), - const SizedBox(height: 4,), - ATextFormField( - initialValue: (model.availability ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - textInputType: TextInputType.text, - onChange: (value){ - model.availability = value; - }, + const SizedBox( + height: 8, ), - const SizedBox(height: 8,), - const ASubTitle("Quantity Needed"), - const SizedBox(height: 4,), - ATextFormField( - initialValue: (model.quantityNeeded ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - textInputType: TextInputType.number, - onChange: (value){ - model.quantityNeeded = value; - }, - ), - const SizedBox(height: 8,), - const ASubTitle("Quantity Reserved"), - const SizedBox(height: 4,), - ATextFormField( - initialValue: (model.quantityReserved ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - textInputType: TextInputType.number, - onChange: (value){ - model.quantityReserved = value; - }, + Divider( + color: Theme.of(context).textTheme.titleMedium.color, ), - const SizedBox(height: 8,), - Divider(color: Theme.of(context).textTheme.titleMedium.color,), ], ); - } + }, ); } } diff --git a/lib/views/widgets/pentry/pentry_ppm_check_list_form.dart b/lib/views/widgets/pentry/pentry_ppm_check_list_form.dart index 201c7498..6bf2d43e 100644 --- a/lib/views/widgets/pentry/pentry_ppm_check_list_form.dart +++ b/lib/views/widgets/pentry/pentry_ppm_check_list_form.dart @@ -7,11 +7,15 @@ import 'package:test_sa/views/widgets/buttons/app_button.dart'; import 'package:test_sa/views/widgets/buttons/app_small_button.dart'; import 'package:test_sa/views/widgets/status/pentry/pentry_task_status_mune.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; + class PentryPPMCheckListForm extends StatefulWidget { final List models; final bool enableValidate; + const PentryPPMCheckListForm({ - Key key, this.models, this.enableValidate, + Key key, + this.models, + this.enableValidate, }) : super(key: key); @override @@ -19,99 +23,112 @@ class PentryPPMCheckListForm extends StatefulWidget { } class _PentryPPMCheckListFormState extends State { - - @override Widget build(BuildContext context) { final subtitle = AppLocalization.of(context).subtitle; return ListView.builder( - padding: EdgeInsets.only( - top: 12 * AppStyle.getScaleFactor(context), - left: 12 * AppStyle.getScaleFactor(context), - right: 12 * AppStyle.getScaleFactor(context), - bottom: 80 * AppStyle.getScaleFactor(context) - ), - itemCount: widget.models.length + 1, - itemBuilder: (context,index){ - if(index == widget.models.length){ - return AButton( - text: subtitle.add, - onPressed: (){ - widget.models.add(PPMCheckList()); - setState(() {}); - }, - ); - } - final model = widget.models[index]; - return ListView( - shrinkWrap: true, - physics: const ClampingScrollPhysics(), - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ASubTitle("#${index+1}"), - if(index != 0) - ASmallButton( - color: Theme.of(context).colorScheme.error, - text: subtitle.delete, - onPressed: (){ - widget.models.remove(model); - setState(() {}); - }, - ), - ], - ), - const SizedBox(height: 8,), - const ASubTitle("Task"), - const SizedBox(height: 4,), - ATextFormField( - initialValue: (model.title ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - textInputType: TextInputType.text, - onChange: (value){ - model.title = value; + padding: EdgeInsets.only( + top: 12 * AppStyle.getScaleFactor(context), left: 12 * AppStyle.getScaleFactor(context), right: 12 * AppStyle.getScaleFactor(context), bottom: 80 * AppStyle.getScaleFactor(context)), + itemCount: widget.models.length + 1, + itemBuilder: (context, index) { + if (index == widget.models.length) { + return AButton( + text: subtitle.add, + onPressed: () { + widget.models.add(PPMCheckList()); + setState(() {}); }, - ), - const SizedBox(height: 8,), - ASubTitle(subtitle.status), - const SizedBox(height: 4,), - PentryTaskStatusMenu( - initialValue: model.status, - onSelect: (status){ - model.status = status; - }, - ), - const SizedBox(height: 8,), - const ASubTitle("Comment"), - const SizedBox(height: 4,), - ATextFormField( - initialValue: (model.comment ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - textInputType: TextInputType.text, - onChange: (value){ - model.comment = value; - }, - ), - const SizedBox(height: 8,), - const ASubTitle("Measured Value"), - const SizedBox(height: 4,), - ATextFormField( - initialValue: (model.measuredValue ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.subtitle1, - textInputType: TextInputType.text, - onChange: (value){ - model.measuredValue = value; - }, - ), - const SizedBox(height: 8,), - Divider(color: Theme.of(context).textTheme.titleMedium.color,), - ], - ); - } - ); + ); + } + final model = widget.models[index]; + return ListView( + shrinkWrap: true, + physics: const ClampingScrollPhysics(), + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ASubTitle("#${index + 1}"), + if (index != 0) + ASmallButton( + color: Theme.of(context).colorScheme.error, + text: subtitle.delete, + onPressed: () { + widget.models.remove(model); + setState(() {}); + }, + ), + ], + ), + const SizedBox( + height: 8, + ), + const ASubTitle("Task"), + const SizedBox( + height: 4, + ), + ATextFormField( + initialValue: (model.title ?? "").toString(), + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.subtitle1, + textInputType: TextInputType.text, + onChange: (value) { + model.title = value; + }, + ), + const SizedBox( + height: 8, + ), + ASubTitle(subtitle.status), + const SizedBox( + height: 4, + ), + PentryTaskStatusMenu( + initialValue: model.status, + onSelect: (status) { + model.status = status; + }, + ), + const SizedBox( + height: 8, + ), + const ASubTitle("Comment"), + const SizedBox( + height: 4, + ), + ATextFormField( + initialValue: (model.comment ?? "").toString(), + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.subtitle1, + textInputType: TextInputType.text, + onChange: (value) { + model.comment = value; + }, + ), + const SizedBox( + height: 8, + ), + const ASubTitle("Measured Value"), + const SizedBox( + height: 4, + ), + ATextFormField( + initialValue: (model.measuredValue ?? "").toString(), + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.subtitle1, + textInputType: TextInputType.text, + onChange: (value) { + model.measuredValue = value; + }, + ), + const SizedBox( + height: 8, + ), + Divider( + color: Theme.of(context).textTheme.titleMedium.color, + ), + ], + ); + }); } } diff --git a/lib/views/widgets/qr/scan_qr.dart b/lib/views/widgets/qr/scan_qr.dart index 0c1cf10b..63c188a2 100644 --- a/lib/views/widgets/qr/scan_qr.dart +++ b/lib/views/widgets/qr/scan_qr.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:qr_code_scanner/qr_code_scanner.dart'; import '../buttons/app_icon_button.dart'; + class ScanQr extends StatefulWidget { const ScanQr({Key key}) : super(key: key); @@ -12,7 +13,6 @@ class ScanQr extends StatefulWidget { } class _ScanQrState extends State { - Barcode result; QRViewController _controller; bool _scanDone = false; @@ -43,31 +43,25 @@ class _ScanQrState extends State { children: [ QRView( key: qrKey, - onQRViewCreated:(QRViewController controller) { + onQRViewCreated: (QRViewController controller) { setState(() { _controller = controller; }); controller.scannedDataStream.listen((scanData) { - if(!_scanDone){ + if (!_scanDone) { _scanDone = true; Navigator.of(context).pop(scanData.code); } - }); }, - overlay: QrScannerOverlayShape( - borderColor: Colors.red, - borderRadius: 10, - borderLength: 30, - borderWidth: 10, - cutOutSize: 280), + overlay: QrScannerOverlayShape(borderColor: Colors.red, borderRadius: 10, borderLength: 30, borderWidth: 10, cutOutSize: 280), ), SafeArea( child: Padding( padding: EdgeInsets.all(12.0), child: AIconButton( - iconData:Icons.arrow_back, - onPressed: (){ + iconData: Icons.arrow_back, + onPressed: () { Navigator.of(context).pop(); }, ), diff --git a/lib/views/widgets/requests/info_row.dart b/lib/views/widgets/requests/info_row.dart index d8fe0bc6..ea60f6e7 100644 --- a/lib/views/widgets/requests/info_row.dart +++ b/lib/views/widgets/requests/info_row.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:test_sa/views/app_style/sizing.dart'; + class RequestInfoRow extends StatelessWidget { final String title; final String info; @@ -7,13 +8,14 @@ class RequestInfoRow extends StatelessWidget { final Widget contentWidget; final Widget infoWidget; - const RequestInfoRow({Key key, this.title, this.info,this.content, this.contentWidget, this.infoWidget}) : super(key: key); + const RequestInfoRow({Key key, this.title, this.info, this.content, this.contentWidget, this.infoWidget}) : super(key: key); + @override Widget build(BuildContext context) { - if(info != null && info.isEmpty){ + if (info != null && info.isEmpty) { return SizedBox.shrink(); } - if(content != null && content.isEmpty){ + if (content != null && content.isEmpty) { return SizedBox.shrink(); } return Column( @@ -23,21 +25,20 @@ class RequestInfoRow extends StatelessWidget { Text( title + " : ", style: Theme.of(context).textTheme.subtitle2.copyWith( - //fontSize: 12 - ), + //fontSize: 12 + ), textScaleFactor: AppStyle.getScaleFactor(context), ), - - if(info != null) - Expanded( - child: Text( - info, - style: Theme.of(context).textTheme.bodyText2, - textAlign: TextAlign.right, - textScaleFactor: AppStyle.getScaleFactor(context), + if (info != null) + Expanded( + child: Text( + info, + style: Theme.of(context).textTheme.bodyText2, + textAlign: TextAlign.right, + textScaleFactor: AppStyle.getScaleFactor(context), + ), ), - ), - if(infoWidget != null) + if (infoWidget != null) Expanded( child: Row( mainAxisAlignment: MainAxisAlignment.end, @@ -48,27 +49,27 @@ class RequestInfoRow extends StatelessWidget { ), ], ), - - if(content != null) - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8), - child: Row( - children: [ - Expanded( - child: Text( - content ?? 'No data found', - style: Theme.of(context).textTheme.bodyText2, - textAlign: TextAlign.center, - textScaleFactor: AppStyle.getScaleFactor(context), + if (content != null) + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Row( + children: [ + Expanded( + child: Text( + content ?? 'No data found', + style: Theme.of(context).textTheme.bodyText2, + textAlign: TextAlign.center, + textScaleFactor: AppStyle.getScaleFactor(context), + ), ), - ), - ], + ], + ), ), + if (contentWidget != null) contentWidget, + Divider( + color: Theme.of(context).primaryColor, ), - if(contentWidget != null) - contentWidget, - Divider(color: Theme.of(context).primaryColor,), ], ); } -} \ No newline at end of file +} diff --git a/lib/views/widgets/requests/request_status.dart b/lib/views/widgets/requests/request_status.dart index c953efc8..7f606a44 100644 --- a/lib/views/widgets/requests/request_status.dart +++ b/lib/views/widgets/requests/request_status.dart @@ -1,35 +1,24 @@ import 'package:flutter/material.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; + class StatusLabel extends StatelessWidget { final String label; final Color color; const StatusLabel({Key key, this.label, this.color}) : super(key: key); - - @override Widget build(BuildContext context) { - return Container( - padding: EdgeInsets.symmetric(vertical: 2,horizontal: 8), + return Container( + padding: EdgeInsets.symmetric(vertical: 2, horizontal: 8), alignment: Alignment.center, - decoration: BoxDecoration( - color: color ?? Colors.green, - borderRadius: BorderRadius.circular( - AppStyle.getBorderRadius(context) - ), - boxShadow: [ - AppStyle.boxShadow - ] - ), + decoration: BoxDecoration(color: color ?? Colors.green, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [AppStyle.boxShadow]), child: Text( label ?? "no status", style: Theme.of(context).textTheme.subtitle2.copyWith( - color: color.computeLuminance() > 0.5 - ? AColors.black : Colors.white, - ), - ) - ); + color: color.computeLuminance() > 0.5 ? AColors.black : Colors.white, + ), + )); } } diff --git a/lib/views/widgets/requests/service_request_item.dart b/lib/views/widgets/requests/service_request_item.dart index 448cb53e..25dd7c79 100644 --- a/lib/views/widgets/requests/service_request_item.dart +++ b/lib/views/widgets/requests/service_request_item.dart @@ -1,4 +1,6 @@ -import 'package:fluttertoast/fluttertoast.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; @@ -10,103 +12,96 @@ import 'package:test_sa/models/user.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/pages/user/requests/report/create_service_report.dart'; -import 'package:test_sa/views/pages/user/requests/report/future_service_report.dart'; import 'package:test_sa/views/widgets/loaders/image_loader.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:test_sa/views/widgets/timer/app_timer.dart'; -import '../../../controllers/http_status_manger/http_status_manger.dart'; class ServiceRequestItem extends StatelessWidget { final int index; final ServiceRequest request; final Function(ServiceRequest) onPressed; + const ServiceRequestItem({Key key, this.request, this.onPressed, this.index}) : super(key: key); @override Widget build(BuildContext context) { Subtitle _subtitle = AppLocalization.of(context).subtitle; - User _user = Provider.of(context,listen: false).user; - final servicesProvider = Provider.of(context,listen: false); - final settingProvider = Provider.of(context,listen: false); - Color itemColor = index % 2 == 0 - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onPrimary; - Color onItemColor = index % 2 != 0 - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onPrimary; + User _user = Provider.of(context, listen: false).user; + final servicesProvider = Provider.of(context, listen: false); + final settingProvider = Provider.of(context, listen: false); + Color itemColor = index % 2 == 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; + Color onItemColor = index % 2 != 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: ElevatedButton( - style: ElevatedButton.styleFrom( - padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8), - primary: itemColor, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - AppStyle.getBorderRadius(context) - ), - ), - ), + style: ElevatedButton.styleFrom( + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8), + primary: itemColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), + ), + ), //padding: EdgeInsets.symmetric(vertical: 8,horizontal: 8), - onPressed: (){ + onPressed: () { onPressed(request); }, child: Row( children: [ //Placeholder(color: onItemColor,fallbackWidth: 80,fallbackHeight: 80,), - _user.type == UsersTypes.normal_user && request.devicePhotos.isEmpty ? SizedBox.shrink(): - SizedBox( - width: 80, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - request.devicePhotos.isEmpty ? SizedBox.shrink(): - Column( - children: [ - SizedBox( - height: 80, - width: 80, - child: ImageLoader( - url: request.devicePhotos.first, - boxFit: BoxFit.cover, - ), - ), - SizedBox(height: 24,), - ], - ), + _user.type == UsersTypes.normal_user && request.devicePhotos.isEmpty + ? SizedBox.shrink() + : SizedBox( + width: 80, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + request.devicePhotos?.isEmpty != false + ? SizedBox.shrink() + : Column( + children: [ + SizedBox( + height: 80, + width: 80, + child: ImageLoader( + url: request.devicePhotos.first, + boxFit: BoxFit.cover, + ), + ), + SizedBox( + height: 24, + ), + ], + ), - _user.type == UsersTypes.engineer ? - Material( - color: onItemColor, - elevation: 6, - shape: CircleBorder(), - child: IconButton( - icon: Icon( - Icons.description, - color: itemColor, - size: 32, - ), - onPressed: (){ - Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => CreateServiceReport( - request: request, + _user.type == UsersTypes.engineer + ? Material( + color: onItemColor, + elevation: 6, + shape: CircleBorder(), + child: IconButton( + icon: Icon( + Icons.description, + color: itemColor, + size: 32, + ), + onPressed: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => CreateServiceReport( + request: request, + )), + ); + }, + ), ) - ), - ); - }, + : SizedBox.shrink(), + //SizedBox(height: 8,), + ], ), - ) :SizedBox.shrink(), - //SizedBox(height: 8,), - - ], - ), + ), + SizedBox( + width: 8, ), - SizedBox(width: 8,), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -120,141 +115,129 @@ class ServiceRequestItem extends StatelessWidget { Row( children: [ Expanded( - child: request.requestCode == null ? SizedBox.shrink(): - Text( - request.requestCode ?? "-----", - style: Theme.of(context).textTheme.headline6.copyWith( - color: onItemColor, - fontSize: 16, - fontWeight: FontWeight.bold - ), - ), - ), - request.engineerName == null ? SizedBox.shrink(): - Text( - request.engineerName ?? "", - style: Theme.of(context).textTheme.subtitle2.copyWith( - color: onItemColor, - fontSize: 12, - fontWeight: FontWeight.normal - ), + child: request.requestCode == null + ? SizedBox.shrink() + : Text( + request.requestCode ?? "-----", + style: Theme.of(context).textTheme.headline6.copyWith(color: onItemColor, fontSize: 16, fontWeight: FontWeight.bold), + ), ), - + request.engineerName == null + ? SizedBox.shrink() + : Text( + request.engineerName ?? "", + style: Theme.of(context).textTheme.subtitle2.copyWith(color: onItemColor, fontSize: 12, fontWeight: FontWeight.normal), + ), ], ), - Divider(color: onItemColor,), - Row( - children: [ - Expanded( - child: request.deviceModel == null ? SizedBox.shrink(): - Text( - request.deviceModel ?? "Model not available", - style: Theme.of(context).textTheme.subtitle2.copyWith( - color: onItemColor, - fontSize: 12, - fontWeight: FontWeight.normal - ), - ), - ), - request.engineerMobile == null ? SizedBox.shrink(): - Text( - request.engineerMobile, - style: Theme.of(context).textTheme.subtitle1.copyWith( - color: onItemColor, - fontSize: 12, - fontWeight: FontWeight.normal - ), - ), - ], + Divider( + color: onItemColor, + ), + Text( + request.deviceNumber, + style: Theme.of(context).textTheme.subtitle2.copyWith(color: onItemColor, fontSize: 12, fontWeight: FontWeight.normal), + ), + Divider( + color: onItemColor, ), - Divider(color: onItemColor,), Row( children: [ Expanded( - child: request.deviceSerialNumber == null ? SizedBox.shrink(): - Text( - request.deviceSerialNumber, - style: Theme.of(context).textTheme.subtitle2.copyWith( - color: onItemColor, - fontSize: 12, - fontWeight: FontWeight.normal - ), - ), + child: request.deviceModel == null + ? SizedBox.shrink() + : Text( + request.deviceModel ?? "Model not available", + style: Theme.of(context).textTheme.subtitle2.copyWith(color: onItemColor, fontSize: 12, fontWeight: FontWeight.normal), + ), ), + request.engineerMobile == null + ? SizedBox.shrink() + : Text( + request.engineerMobile, + style: Theme.of(context).textTheme.subtitle1.copyWith(color: onItemColor, fontSize: 12, fontWeight: FontWeight.normal), + ), ], ), - request.deviceEnName == null ? SizedBox.shrink(): + Divider( + color: onItemColor, + ), Row( children: [ Expanded( - child: Text( - request.deviceEnName, - style: Theme.of(context).textTheme.subtitle1.copyWith( - color: onItemColor, - fontSize: 12, - fontWeight: FontWeight.normal - ), - ), + child: request.deviceSerialNumber == null + ? SizedBox.shrink() + : Text( + request.deviceSerialNumber, + style: Theme.of(context).textTheme.subtitle2.copyWith(color: onItemColor, fontSize: 12, fontWeight: FontWeight.normal), + ), ), ], ), + request.deviceEnName == null + ? SizedBox.shrink() + : Row( + children: [ + Expanded( + child: Text( + request.deviceEnName, + style: Theme.of(context).textTheme.subtitle1.copyWith(color: onItemColor, fontSize: 12, fontWeight: FontWeight.normal), + ), + ), + ], + ), ], ), ), - ], ), - - Divider(color: onItemColor,), + Divider( + color: onItemColor, + ), Center( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 8), child: Text( - request.maintenanceIssue ?? "No maintenance issue found", - style: Theme.of(context).textTheme.subtitle1.copyWith( - color: onItemColor - ), + request.callComments ?? "No maintenance issue found", + style: Theme.of(context).textTheme.subtitle1.copyWith(color: onItemColor), textAlign: TextAlign.center, ), ), ), - Divider(color: onItemColor,), + Divider( + color: onItemColor, + ), Row( children: [ Text( request.date ?? "Date not available", - style: Theme.of(context).textTheme.subtitle2.copyWith( - color: onItemColor - ), + style: Theme.of(context).textTheme.subtitle2.copyWith(color: onItemColor), ), Spacer(), - StatusLabel(label: request.statusLabel, - color: AColors.getRequestStatusColor(request.statusValue)), + StatusLabel(label: request.statusLabel, color: AColors.getRequestStatusColor(request.statusValue)), ], ), - request.nextVisitDate == null ? SizedBox.shrink() : - Column( - children: [ - Divider(color: onItemColor,), - Row( - children: [ - Text( - _subtitle.nextVisitDate, - style: Theme.of(context).textTheme.subtitle2.copyWith( - color: onItemColor + request.nextVisitDate == null + ? SizedBox.shrink() + : Column( + children: [ + Divider( + color: onItemColor, ), - ), - Spacer(), - Text( - DateFormat('EE dd/MM/yyyy').format(request.nextVisitDate), - style: Theme.of(context).textTheme.subtitle2.copyWith( - color: onItemColor + Row( + children: [ + Text( + _subtitle.nextVisitDate, + style: Theme.of(context).textTheme.subtitle2.copyWith(color: onItemColor), + ), + Spacer(), + Text( + DateFormat('EE dd/MM/yyyy').format(request.nextVisitDate), + style: Theme.of(context).textTheme.subtitle2.copyWith(color: onItemColor), + ), + ], ), - ), - ], - ), - ], - ), + ], + ), ], ), ), diff --git a/lib/views/widgets/requests/service_request_list.dart b/lib/views/widgets/requests/service_request_list.dart index 7cd71079..29fa65e1 100644 --- a/lib/views/widgets/requests/service_request_list.dart +++ b/lib/views/widgets/requests/service_request_list.dart @@ -6,6 +6,7 @@ import 'package:test_sa/views/pages/user/requests/request_details.dart'; import 'package:test_sa/views/widgets/loaders/lazy_loading.dart'; import 'package:test_sa/views/widgets/loaders/no_item_found.dart'; import 'package:test_sa/views/widgets/requests/service_request_item.dart'; + class ServiceRequestsList extends StatelessWidget { final List requests; final bool nextPage; @@ -15,32 +16,31 @@ class ServiceRequestsList extends StatelessWidget { @override Widget build(BuildContext context) { - Subtitle _subtitle = AppLocalization.of(context).subtitle; - if(requests.length == 0){ - return NoItemFound(message: _subtitle.noServiceRequestFound,); + if (requests.length == 0) { + return NoItemFound( + message: _subtitle.noServiceRequestFound, + ); } return LazyLoading( nextPage: nextPage, onLazyLoad: onLazyLoad, child: ListView.builder( - //physics: BouncingScrollPhysics(), - itemCount: requests.length, - padding: EdgeInsets.symmetric(horizontal: 16,vertical: 8), - itemBuilder: (context,itemIndex){ + //physics: BouncingScrollPhysics(), + itemCount: requests.length, + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), + itemBuilder: (context, itemIndex) { return ServiceRequestItem( index: itemIndex, request: requests[itemIndex], - onPressed: (request){ - Navigator.of(context).push( - MaterialPageRoute( - builder: (_)=> RequestDetailsPage(serviceRequest: request,) - ) - ); + onPressed: (request) { + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => RequestDetailsPage( + serviceRequest: request, + ))); }, ); - } - ), + }), ); } } diff --git a/lib/views/widgets/requests/service_request_update_dialog.dart b/lib/views/widgets/requests/service_request_update_dialog.dart index bde17432..ce8cae93 100644 --- a/lib/views/widgets/requests/service_request_update_dialog.dart +++ b/lib/views/widgets/requests/service_request_update_dialog.dart @@ -1,37 +1,33 @@ import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/http_status_manger/http_status_manger.dart'; +import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/service_requests_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; -import 'package:test_sa/models/service_request/service_request.dart'; -import 'package:test_sa/models/service_request/service_request_search.dart'; import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/app_style/sizing.dart'; -import 'package:test_sa/views/widgets/buttons/app_button.dart'; import 'package:test_sa/views/widgets/buttons/app_small_button.dart'; import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; -import 'package:test_sa/views/widgets/hospitals/hospital_auto_complete_field.dart'; -import 'package:flutter/material.dart'; -import 'package:test_sa/views/widgets/status/employee/employee_mune.dart'; - -import '../app_text_form_field.dart'; +import 'package:test_sa/views/widgets/status/employee/assigned_to_mune.dart'; class ServiceRequestsUpdateDialog extends StatefulWidget { final ServiceRequest request; + const ServiceRequestsUpdateDialog({ - Key key, this.request, + Key key, + this.request, }) : super(key: key); + @override State createState() => _ServiceRequestsUpdateDialogState(); } -class _ServiceRequestsUpdateDialogState extends State - with TickerProviderStateMixin{ - +class _ServiceRequestsUpdateDialogState extends State with TickerProviderStateMixin { DateTime _dateTime; Lookup _employee; Subtitle _subtitle; @@ -42,7 +38,7 @@ class _ServiceRequestsUpdateDialogState extends State _formKey = GlobalKey(); _update() async { - if(_dateTime == null && _employee == null){ + if (_dateTime == null && _employee == null) { Fluttertoast.showToast( msg: _subtitle.noDateFound, ); @@ -58,14 +54,8 @@ class _ServiceRequestsUpdateDialogState extends State(context,listen: false); - _settingProvider = Provider.of(context,listen: false); - _serviceRequestsProvider = Provider.of(context,listen: false); - return Column( + _subtitle = AppLocalization.of(context).subtitle; + _userProvider = Provider.of(context, listen: false); + _settingProvider = Provider.of(context, listen: false); + _serviceRequestsProvider = Provider.of(context, listen: false); + return Column( mainAxisSize: MainAxisSize.min, children: [ SizedBox( - // height: MediaQuery.of(context).size.height / 1.2, + // height: MediaQuery.of(context).size.height / 1.2, child: Form( key: _formKey, child: Padding( @@ -99,18 +89,19 @@ class _ServiceRequestsUpdateDialogState extends State AssetTransferSearchDialogState(); +} + +class AssetTransferSearchDialogState extends State with TickerProviderStateMixin { + DeviceTransferSearch _search; + final GlobalKey _formKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _search = DeviceTransferSearch(); + _search.fromSearch(widget.initialSearchValue); + } + + @override + Widget build(BuildContext context) { + Subtitle subtitle = AppLocalization.of(context).subtitle; + return SizedBox( + height: MediaQuery.of(context).size.height / 1.3, + child: Form( + key: _formKey, + child: ListView( + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ASmallButton( + text: subtitle.cancel, + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ASmallButton( + text: subtitle.search, + onPressed: () { + if (!_formKey.currentState.validate()) { + return; + } + _formKey.currentState.save(); + Navigator.of(context).pop(_search); + }, + ) + ], + ), + ASwitchButton( + title: "Most Recent", + value: _search.mostRecent ?? false, + onChange: (value) { + _search.mostRecent = value; + setState(() {}); + }, + ), + SizedBox( + height: 8.0 * AppStyle.getScaleFactor(context), + ), + ATextFormField( + initialValue: _search.assetNumber, + hintText: subtitle.assetNumber, + style: Theme.of(context).textTheme.headline6, + textInputAction: TextInputAction.search, + onAction: () { + if (!_formKey.currentState.validate()) { + return; + } + _formKey.currentState.save(); + Navigator.of(context).pop(_search); + }, + onSaved: (value) { + _search.assetNumber = value; + }, + ), + SizedBox( + height: 8.0 * AppStyle.getScaleFactor(context), + ), + ATextFormField( + initialValue: _search.assetName, + hintText: subtitle.assetName, + style: Theme.of(context).textTheme.headline6, + textInputAction: TextInputAction.search, + onAction: () { + if (!_formKey.currentState.validate()) { + return; + } + _formKey.currentState.save(); + Navigator.of(context).pop(_search); + }, + onSaved: (value) { + _search.site = value; + }, + ), + SizedBox( + height: 8.0 * AppStyle.getScaleFactor(context), + ), + ATextFormField( + initialValue: _search.site, + hintText: subtitle.site, + style: Theme.of(context).textTheme.headline6, + textInputAction: TextInputAction.search, + onAction: () { + if (!_formKey.currentState.validate()) { + return; + } + _formKey.currentState.save(); + Navigator.of(context).pop(_search); + }, + onSaved: (value) { + _search.assetName = value; + }, + ), + SizedBox( + height: 8.0 * AppStyle.getScaleFactor(context), + ), + const ASubTitle("Request Date"), + const SizedBox(height: 4), + ServiceReportVisitDateOperator( + initialValue: _search.dateOperator, + onSelect: (status) { + _search.dateOperator = status; + setState(() {}); + }, + ), + Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + if (_search?.dateOperator?.name?.toLowerCase()?.contains("between") ?? false) const ASubTitle("From"), + ADatePicker( + date: DateTime.tryParse(_search.from ?? ""), + from: DateTime(1950), + onDatePicker: (date) { + _search.from = date?.toIso8601String(); + setState(() {}); + }, + ), + ], + ), + ), + if (_search?.dateOperator?.name?.toLowerCase()?.contains("between") ?? false) const SizedBox(width: 16), + if (_search?.dateOperator?.name?.toLowerCase()?.contains("between") ?? false) + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const ASubTitle("To"), + ADatePicker( + date: DateTime.tryParse(_search.to ?? ""), + from: DateTime(1950), + onDatePicker: (date) { + _search.to = date?.toIso8601String(); + setState(() {}); + }, + ), + ], + ), + ), + ], + ), + const SizedBox(width: 16), + Visibility( + visible: _search.toMap().isNotEmpty, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), + child: AButton( + padding: EdgeInsets.zero, + text: subtitle.clearSearch, + onPressed: () { + _search = DeviceTransferSearch(); + Navigator.of(context).pop(_search); + }, + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/views/widgets/search/filter_item.dart b/lib/views/widgets/search/filter_item.dart index 10d708a0..7129405c 100644 --- a/lib/views/widgets/search/filter_item.dart +++ b/lib/views/widgets/search/filter_item.dart @@ -8,22 +8,24 @@ class FilterItem extends StatelessWidget { final Lookup status; final VoidCallback onSelected; - const FilterItem({ - Key key, - this.status, - this.isSelected, - this.onSelected - }) : super(key: key); + const FilterItem({Key key, this.status, this.isSelected, this.onSelected}) : super(key: key); - Color getStatusColor(){ - switch(status.id){ - case 0: return AColors.green; - case 4: return AColors.deepRed; - case 6: return AColors.green; - case 5: return AColors.orange; - case 8: return AColors.green; - case 9: return AColors.orange; - default : return AColors.grey; + Color getStatusColor() { + switch (status.id) { + case 0: + return AColors.green; + case 4: + return AColors.deepRed; + case 6: + return AColors.green; + case 5: + return AColors.orange; + case 8: + return AColors.green; + case 9: + return AColors.orange; + default: + return AColors.grey; } } @@ -36,22 +38,17 @@ class FilterItem extends StatelessWidget { child: ElevatedButton( style: ElevatedButton.styleFrom( padding: EdgeInsets.symmetric(horizontal: 8), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - AppStyle.getBorderRadius(context) - ) - ), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context))), primary: getStatusColor(), ), child: Text( - status.label??"", + status.name ?? "", style: Theme.of(context).textTheme.bodyText1.copyWith( - color:getStatusColor().computeLuminance() > 0.5 - ? AColors.black : Colors.white, - ), + color: getStatusColor().computeLuminance() > 0.5 ? AColors.black : Colors.white, + ), textScaleFactor: AppStyle.getScaleFactor(context), ), - onPressed:onSelected, + onPressed: onSelected, ), ), ); diff --git a/lib/views/widgets/search/service_request_search_bar.dart b/lib/views/widgets/search/service_request_search_bar.dart index a1f78945..682b4177 100644 --- a/lib/views/widgets/search/service_request_search_bar.dart +++ b/lib/views/widgets/search/service_request_search_bar.dart @@ -7,34 +7,47 @@ import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; import 'package:test_sa/views/widgets/buttons/app_small_button.dart'; import 'package:test_sa/views/widgets/hospitals/hospital_auto_complete_field.dart'; +import 'package:test_sa/views/widgets/status/service_request/service_request_status_mune.dart'; +import 'package:test_sa/views/widgets/switch_button.dart'; +import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; +import '../../../models/call_request_for_work_order_model.dart'; +import '../../../models/engineer.dart'; import '../app_text_form_field.dart'; -import 'filter_item.dart'; +import '../date_and_time/date_picker.dart'; +import '../status/report/service_report_all_users.dart'; +import '../status/report/service_report_visit_date_operator.dart'; + class ServiceRequestsSearchDialog extends StatefulWidget { final ServiceRequestSearch initialSearchValue; final bool expandedSearch; final Function(ServiceRequestSearch) onSearch; - const ServiceRequestsSearchDialog({ - Key key, - this.initialSearchValue, - this.expandedSearch, - this.onSearch - }) : super(key: key); + const ServiceRequestsSearchDialog({Key key, this.initialSearchValue, this.expandedSearch, this.onSearch}) : super(key: key); @override _ServiceRequestsSearchDialogState createState() => _ServiceRequestsSearchDialogState(); } -class _ServiceRequestsSearchDialogState extends State - with TickerProviderStateMixin{ +class _ServiceRequestsSearchDialogState extends State with TickerProviderStateMixin { ServiceRequestSearch _search; List status = [ - Lookup(label: "New", id: 4,), - - Lookup(label: "Repaired", id: 6,), - Lookup(label: "Repeated", id: 8), - Lookup(label: "Closed", id: 9,), - Lookup(label: "Under Repair", id: 5,), + Lookup( + name: "New", + id: 4, + ), + Lookup( + name: "Repaired", + id: 6, + ), + Lookup(name: "Repeated", id: 8), + Lookup( + name: "Closed", + id: 9, + ), + Lookup( + name: "Under Repair", + id: 5, + ), ]; final GlobalKey _formKey = GlobalKey(); @@ -45,141 +58,270 @@ class _ServiceRequestsSearchDialogState extends State _VisitsSearchDialogState(); } -class _VisitsSearchDialogState extends State - with TickerProviderStateMixin{ +class _VisitsSearchDialogState extends State with TickerProviderStateMixin { VisitsSearch _search; List status = [ - Lookup(label: "Done", id: 0,), - Lookup(label: "Not Yet", id: 1), - Lookup(label: "On Hold", id: 2,), + Lookup( + name: "Done", + id: 0, + ), + Lookup(name: "Not Yet", id: 1), + Lookup( + name: "On Hold", + id: 2, + ), ]; List contactStatus = [ - Lookup(label: "Hospital Employee", key: "H",), - Lookup(label: "Under Warranty", key: "CW"), - Lookup(label: "Under Maintenance Contract", key: "CC",), + // Lookup(name: "Hospital Employee", value: "H",), + // Lookup(name: "Under Warranty", value: "CW"), + // Lookup(name: "Under Maintenance Contract", value: "CC",), ]; - final GlobalKey _formKey = GlobalKey(); @override @@ -52,182 +54,278 @@ class _VisitsSearchDialogState extends State _search = VisitsSearch(); _search.fromSearch(widget.initialSearchValue); } + @override Widget build(BuildContext context) { Subtitle _subtitle = AppLocalization.of(context).subtitle; DateTime today = DateTime.now(); - return SizedBox( + return SizedBox( height: MediaQuery.of(context).size.height / 1.3, child: Form( key: _formKey, child: ListView( - padding: const EdgeInsets.symmetric(vertical: 8,horizontal: 16), + // shrinkWrap: true, + // physics: const ClampingScrollPhysics(), + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ASmallButton( text: _subtitle.cancel, - onPressed: (){ + onPressed: () { Navigator.of(context).pop(); }, ), - ASmallButton( text: _subtitle.search, - onPressed: (){ - if(!_formKey.currentState.validate()) + onPressed: () { + if (!_formKey.currentState.validate()) { return; + } _formKey.currentState.save(); Navigator.of(context).pop(_search); }, ) ], ), + ASwitchButton( + title: "Most Recent", + value: _search.mostRecent ?? false, + onChange: (value) { + _search.mostRecent = value; + setState(() {}); + }, + ), + SizedBox( + height: 8.0 * AppStyle.getScaleFactor(context), + ), ATextFormField( - initialValue: _search.deviceSerialNumber, - hintText: _subtitle.serialNumber, - style: Theme.of(context).textTheme.headline6, + initialValue: _search.deviceNumber, + hintText: _subtitle.assetNumber, + style: Theme.of(context).textTheme.headline6, textInputAction: TextInputAction.search, - onAction: (){ - if(!_formKey.currentState.validate()) + onAction: () { + if (!_formKey.currentState.validate()) { return; + } _formKey.currentState.save(); Navigator.of(context).pop(_search); }, - onSaved: (value){ - _search.deviceSerialNumber = value; + onSaved: (value) { + _search.deviceNumber = value; }, ), - SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),), - HospitalAutoCompleteField( - initialValue: _search.hospitalName, - onSave: (value){ - _search.hospitalName = value; - }, - onSearch: (value){ - _search.hospitalName = value; - Navigator.of(context).pop(_search); - }, + SizedBox( + height: 8.0 * AppStyle.getScaleFactor(context), ), - SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),), ATextFormField( - initialValue: _search.brand, - hintText: _subtitle.brand, - style: Theme.of(context).textTheme.headline6, + initialValue: _search.deviceName, + hintText: _subtitle.assetName, + style: Theme.of(context).textTheme.headline6, textInputAction: TextInputAction.search, - onAction: (){ - if(!_formKey.currentState.validate()) + onAction: () { + if (!_formKey.currentState.validate()) { return; + } _formKey.currentState.save(); Navigator.of(context).pop(_search); }, - onSaved: (value){ - _search.brand = value; + onSaved: (value) { + _search.deviceName = value; }, ), - SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),), + SizedBox( + height: 8.0 * AppStyle.getScaleFactor(context), + ), ATextFormField( - initialValue: _search.model, - hintText: _subtitle.model, - style: Theme.of(context).textTheme.headline6, + initialValue: _search.deviceSerialNumber, + hintText: _subtitle.serialNumber, + style: Theme.of(context).textTheme.headline6, textInputAction: TextInputAction.search, - onAction: (){ - if(!_formKey.currentState.validate()) + onAction: () { + if (!_formKey.currentState.validate()) { return; + } _formKey.currentState.save(); Navigator.of(context).pop(_search); }, - onSaved: (value){ - _search.model = value; + onSaved: (value) { + _search.deviceSerialNumber = value; }, ), - SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),), + SizedBox( + height: 8.0 * AppStyle.getScaleFactor(context), + ), + HospitalAutoCompleteField( + initialValue: _search.hospital?.name, + // onSave: (value){ + // _search.hospital = value; + // }, + onSearch: (value) { + _search.hospital = value; + Navigator.of(context).pop(_search); + }, + ), + // SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),), + // ATextFormField( + // initialValue: _search.brand, + // hintText: _subtitle.brand, + // style: Theme.of(context).textTheme.headline6, + // textInputAction: TextInputAction.search, + // onAction: (){ + // if(!_formKey.currentState.validate()) { + // return; + // } + // _formKey.currentState.save(); + // Navigator.of(context).pop(_search); + // }, + // onSaved: (value){ + // _search.brand = value; + // }, + // ), + SizedBox( + height: 8.0 * AppStyle.getScaleFactor(context), + ), + AutoCompleteModelField( + initialValue: _search.model, + onPick: (lookup) { + _search.model = lookup; + Navigator.of(context).pop(_search); + }, + ), + // ATextFormField( + // initialValue: _search.model, + // hintText: _subtitle.model, + // style: Theme.of(context).textTheme.headline6, + // textInputAction: TextInputAction.search, + // onAction: (){ + // if(!_formKey.currentState.validate()) { + // return; + // } + // _formKey.currentState.save(); + // Navigator.of(context).pop(_search); + // }, + // onSaved: (value){ + // _search.model = value; + // }, + // ), + SizedBox( + height: 8.0 * AppStyle.getScaleFactor(context), + ), ASubTitle(_subtitle.status), - SizedBox(height: 4.0 * AppStyle.getScaleFactor(context),), - Wrap( - spacing: 10, - runSpacing: 10, - children: List.generate( - status.length, - (index) { - bool isSelected = _search.statusValue == status[index].id; - return FilterItem( - isSelected: isSelected, - onSelected: (){ - if(isSelected) - _search.statusValue = null; - else - _search.statusValue = status[index].id; - - setState(() {}); - }, - status: status[index], - ); - } - - ), + SizedBox( + height: 4.0 * AppStyle.getScaleFactor(context), + ), + PentryVisitsStatusMenu( + initialValue: _search.statusValue, + onSelect: (status) { + _search.statusValue = status; + }, + ), + // Wrap( + // spacing: 10, + // runSpacing: 10, + // children: List.generate( + // status.length, + // (index) { + // bool isSelected = _search.statusValue == status[index].id; + // return FilterItem( + // isSelected: isSelected, + // onSelected: (){ + // if(isSelected) { + // _search.statusValue = null; + // } else { + // _search.statusValue = status[index].id; + // } + // + // setState(() {}); + // }, + // status: status[index], + // ); + // } + // + // ), + // ), + SizedBox( + height: 8.0 * AppStyle.getScaleFactor(context), ), - SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),), ASubTitle(_subtitle.contactStatus), - SizedBox(height: 4.0 * AppStyle.getScaleFactor(context),), - Wrap( - spacing: 10, - runSpacing: 10, - children: List.generate( - contactStatus.length, - (index) { - bool isSelected = _search.contactStatus == contactStatus[index].key; - return FilterItem( - isSelected: isSelected, - onSelected: (){ - if(isSelected) - _search.contactStatus = null; - else - _search.contactStatus = contactStatus[index].key; - - setState(() {}); - }, - status: contactStatus[index], - ); - } - - ), + SizedBox( + height: 4.0 * AppStyle.getScaleFactor(context), + ), + AssignedToMenu( + initialValue: _search.contactStatus, + onSelect: (status) { + _search.contactStatus = status; + }, + ), + // Wrap( + // spacing: 10, + // runSpacing: 10, + // children: List.generate( + // contactStatus.length, + // (index) { + // bool isSelected = _search.contactStatus == contactStatus[index]; + // return FilterItem( + // isSelected: isSelected, + // onSelected: (){ + // if(isSelected) { + // _search.contactStatus = null; + // } else { + // _search.contactStatus = contactStatus[index]; + // } + // + // setState(() {}); + // }, + // status: contactStatus[index], + // ); + // } + // + // ), + // ), + SizedBox( + height: 8.0 * AppStyle.getScaleFactor(context), ), - SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),), ASubTitle(_subtitle.actualDate), - SizedBox(height: 4.0 * AppStyle.getScaleFactor(context),), + SizedBox( + height: 4.0 * AppStyle.getScaleFactor(context), + ), FromToDateBar( - from: _search.actualDateFrom , + from: _search.actualDateFrom, to: _search.actualDateTo, - onPickFrom: (date){ + onPickFrom: (date) { _search.actualDateFrom = date; }, - onPickTo: (date){ + onPickTo: (date) { _search.actualDateTo = date; }, ), - SizedBox(height: 8.0 * AppStyle.getScaleFactor(context),), + SizedBox( + height: 8.0 * AppStyle.getScaleFactor(context), + ), ASubTitle(_subtitle.expectDate), - SizedBox(height: 4.0 * AppStyle.getScaleFactor(context),), + SizedBox( + height: 4.0 * AppStyle.getScaleFactor(context), + ), FromToDateBar( from: _search.expectedDateFrom ?? DateTime(today.year, today.month, 1), - to: _search.expectedDateTo ?? DateTime(today.year, (today.month +1).clamp(1, 12) , today.month == 12 ? 31 : 0), - onPickFrom: (date){ + to: _search.expectedDateTo ?? DateTime(today.year, (today.month + 1).clamp(1, 12), today.month == 12 ? 31 : 0), + onPickFrom: (date) { _search.expectedDateFrom = date; }, - onPickTo: (date){ + onPickTo: (date) { _search.expectedDateTo = date; }, ), Visibility( - visible: _search.toSearchString().isNotEmpty, + visible: _search.toMap().isNotEmpty, child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8,horizontal: 16), + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), child: AButton( padding: EdgeInsets.zero, text: _subtitle.clearSearch, - onPressed: (){ + onPressed: () { _search = VisitsSearch(); Navigator.of(context).pop(_search); }, diff --git a/lib/views/widgets/sound/record_sound.dart b/lib/views/widgets/sound/record_sound.dart index 5ca797e4..d10119e6 100644 --- a/lib/views/widgets/sound/record_sound.dart +++ b/lib/views/widgets/sound/record_sound.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_sound/flutter_sound.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:rive/rive.dart'; import 'package:test_sa/views/widgets/buttons/app_icon_button2.dart'; @@ -11,8 +12,9 @@ import '../../app_style/sizing.dart'; class RecordSound extends StatefulWidget { final Function(String) onRecord; + final bool enabled; - const RecordSound({Key key, @required this.onRecord}) : super(key: key); + const RecordSound({Key key, @required this.onRecord, this.enabled = true}) : super(key: key); @override State createState() => _RecordSoundState(); @@ -22,7 +24,6 @@ class _RecordSoundState extends State { FlutterSoundRecorder _myRecorder = FlutterSoundRecorder(); bool _recorderIsOpened = false; bool _recording = false; - bool _fastTab = false; String _record; Artboard _rive; @@ -67,11 +68,14 @@ class _RecordSoundState extends State { } _startRecording() async { - _fastTab = false; // await Permission.camera PermissionStatus status = await Permission.microphone.request(); if (!status.isGranted) { - return; + PermissionStatus status = await Permission.microphone.request(); + if (!status.isGranted) { + Fluttertoast.showToast(msg: "Permission Denied"); + return; + } } _rive.addController(SimpleAnimation('recording')); if (!_recorderIsOpened) { @@ -87,7 +91,6 @@ class _RecordSoundState extends State { _stopRecording() async { if (!_recording) { - _fastTab = true; setState(() {}); return; } @@ -114,11 +117,11 @@ class _RecordSoundState extends State { @override Widget build(BuildContext context) { return Container( - padding: EdgeInsets.only(left: 12, right: 0), + padding: const EdgeInsets.only(left: 12, right: 0), decoration: BoxDecoration( - color: Color(0xfff5f5f5), + color: const Color(0xfff5f5f5), border: Border.all( - color: Color(0xffefefef), + color: const Color(0xffefefef), ), borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), ), @@ -178,20 +181,23 @@ class _RecordSoundState extends State { color: Colors.transparent, child: GestureDetector( //key: ValueKey("voice"), - child: const Padding( - padding: EdgeInsets.all(12.0), - child: Icon(Icons.mic), - ), - - onTapDown: (TapDownDetails details) async { - _startRecording(); - }, - onTapUp: (TapUpDetails details) async { - _stopRecording(); - }, - onTapCancel: () async { - _cancelRecording(); - }, + onTapDown: widget.enabled + ? (TapDownDetails details) async { + _startRecording(); + } + : null, + onTapUp: widget.enabled + ? (TapUpDetails details) async { + _stopRecording(); + } + : null, + onTapCancel: widget.enabled + ? () async { + _cancelRecording(); + } + : null, + //key: ValueKey("voice"), + child: const Padding(padding: EdgeInsets.all(12.0), child: Icon(Icons.mic)), ), ), ], diff --git a/lib/views/widgets/sound/sound_player.dart b/lib/views/widgets/sound/sound_player.dart index 1422f24e..74cf2571 100644 --- a/lib/views/widgets/sound/sound_player.dart +++ b/lib/views/widgets/sound/sound_player.dart @@ -1,5 +1,3 @@ -import 'dart:typed_data'; - import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/material.dart'; import 'package:test_sa/views/app_style/sizing.dart'; @@ -7,7 +5,6 @@ import 'package:test_sa/views/app_style/sizing.dart'; import '../../app_style/colors.dart'; class ASoundPlayer extends StatefulWidget { - final String audio; const ASoundPlayer({Key key, this.audio}) : super(key: key); @@ -17,7 +14,6 @@ class ASoundPlayer extends StatefulWidget { } class _ASoundPlayerState extends State { - //FlutterSoundPlayer _myPlayer = FlutterSoundPlayer(); bool _sliderMoving = false; Duration _audioTime; @@ -27,8 +23,8 @@ class _ASoundPlayerState extends State { bool _failedToLoad = false; AudioPlayer _audioPlayer; - Widget _getAudioButton(){ - switch(_audioPlayer.state){ + Widget _getAudioButton() { + switch (_audioPlayer.state) { case PlayerState.playing: return IconButton( icon: const Icon(Icons.pause_rounded), @@ -36,83 +32,71 @@ class _ASoundPlayerState extends State { _failedToLoad = false; await _audioPlayer.pause(); rebuild(); - } - ); + }); case PlayerState.paused: - return IconButton( + return IconButton( icon: const Icon(Icons.play_arrow_rounded), onPressed: () async { _failedToLoad = false; await _audioPlayer.resume(); rebuild(); - } - ); + }); case PlayerState.completed: - return IconButton( + return IconButton( icon: const Icon(Icons.replay_rounded), onPressed: () async { _failedToLoad = false; await _audioPlayer.stop(); await _audioPlayer.resume(); rebuild(); - } - ); + }); case PlayerState.stopped: return IconButton( - icon: Icon( _isLocalFile - ? Icons.play_circle_fill_outlined - : Icons.download_rounded - - ), + icon: Icon(_isLocalFile ? Icons.play_circle_fill_outlined : Icons.download_rounded), onPressed: () async { _failedToLoad = false; try { await _audioPlayer.play( - _isLocalFile? - DeviceFileSource(_audio):UrlSource(_audio), + _isLocalFile ? DeviceFileSource(_audio) : UrlSource(_audio), ); rebuild(); } on Exception catch (e) { _failedToLoad = true; } - } - ); - default: return IconButton( - icon: const Icon( Icons.replay_rounded), - onPressed: () async { - _failedToLoad = false; - try { - _audioPlayer.seek(const Duration(milliseconds: 0)); - _audioPlayer.stop(); - await _audioPlayer.play( - _isLocalFile? - DeviceFileSource(_audio):UrlSource(_audio), - ); - rebuild(); - } on Exception catch (e) { - _failedToLoad = true; - } - } - ); + }); + default: + return IconButton( + icon: const Icon(Icons.replay_rounded), + onPressed: () async { + _failedToLoad = false; + + try { + _audioPlayer.seek(const Duration(milliseconds: 0)); + _audioPlayer.stop(); + await _audioPlayer.play( + _isLocalFile ? DeviceFileSource(_audio) : UrlSource(_audio), + ); + rebuild(); + } on Exception catch (e) { + _failedToLoad = true; + } + }); } } String format(Duration d) { - if(d == null) - return "00:00"; + if (d == null) return "00:00"; return d.toString().substring(2, 7); } - rebuild(){ + rebuild() { if (!mounted) return; setState(() {}); } bool _isLocalUrl(String url) { - if(url?.isEmpty != false) return false; - return url.startsWith("/") || - url.startsWith("file://") || - url.substring(1).startsWith(':\\'); + if (url?.isEmpty != false) return false; + return url.startsWith("/") || url.startsWith("file://") || url.substring(1).startsWith(':\\'); } @override @@ -123,14 +107,16 @@ class _ASoundPlayerState extends State { _audio = widget.audio; _isLocalFile = _isLocalUrl(_audio); _audioPlayer.setReleaseMode(ReleaseMode.stop); - if(_isLocalFile){ - _audioPlayer.setSourceDeviceFile(_audio).then((value) {rebuild();}); - } else{ + if (_isLocalFile) { + _audioPlayer.setSourceDeviceFile(_audio).then((value) { + rebuild(); + }); + } else { _audioPlayer.setReleaseMode(ReleaseMode.stop); } // set up listeners - _audioPlayer.onPositionChanged.listen((Duration duration) { - if(!_sliderMoving){ + _audioPlayer.onPositionChanged.listen((Duration duration) { + if (!_sliderMoving) { _audioPosition = duration; rebuild(); } @@ -140,7 +126,7 @@ class _ASoundPlayerState extends State { //_audioPosition = _audioTime; rebuild(); }); - _audioPlayer.onDurationChanged.listen((Duration duration) { + _audioPlayer.onDurationChanged.listen((Duration duration) { _audioTime = duration; rebuild(); }); @@ -152,20 +138,19 @@ class _ASoundPlayerState extends State { @override void dispose() { super.dispose(); - // _myPlayer.closeAudioSession(); + // _myPlayer.closeAudioSession(); _audioPlayer.release(); _audioPlayer.dispose(); - } @override Widget build(BuildContext context) { - if(_audio != widget.audio){ + if (_audio != widget.audio) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { _audio = widget.audio; - if(_isLocalFile){ + if (_isLocalFile) { await _audioPlayer.setSourceDeviceFile(_audio); - }else{ + } else { await _audioPlayer.setSourceUrl(_audio); } _audioPlayer.seek(const Duration(milliseconds: 0)); @@ -173,34 +158,29 @@ class _ASoundPlayerState extends State { rebuild(); }); } - return Column( + return Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Row( children: [ - Material( - color: Colors.transparent, - child: _getAudioButton() - ), + Material(color: Colors.transparent, child: _getAudioButton()), Expanded( child: Slider( - value: _audioPosition?.inMilliseconds?.toDouble() ?? 0.0, - min: 0, - max: _audioTime?.inMilliseconds?.toDouble() ?? 60.0, - onChangeStart: (value){ - _sliderMoving = true; - }, - onChanged: (value){ - _audioPosition = Duration(milliseconds: value.round()); - rebuild(); - }, - onChangeEnd: (value){ - _sliderMoving = false; - _audioPlayer.seek(Duration(milliseconds: value.round())); - rebuild(); - } - - ), + value: _audioPosition?.inMilliseconds?.toDouble() ?? 0.0, + min: 0, + max: _audioTime?.inMilliseconds?.toDouble() ?? 60.0, + onChangeStart: (value) { + _sliderMoving = true; + }, + onChanged: (value) { + _audioPosition = Duration(milliseconds: value.round()); + rebuild(); + }, + onChangeEnd: (value) { + _sliderMoving = false; + _audioPlayer.seek(Duration(milliseconds: value.round())); + rebuild(); + }), ), ], ), @@ -213,12 +193,9 @@ class _ASoundPlayerState extends State { children: [ Text( "Failed to load", - style: Theme.of(context).textTheme.overline.copyWith( - color: AColors.red - ), + style: Theme.of(context).textTheme.overline.copyWith(color: AColors.red), textScaleFactor: AppStyle.getScaleFactor(context), ), - ], ), ), diff --git a/lib/views/widgets/speech_to_text/speech_to_text.dart b/lib/views/widgets/speech_to_text/speech_to_text.dart index 7d4b96d7..7d9e1d55 100644 --- a/lib/views/widgets/speech_to_text/speech_to_text.dart +++ b/lib/views/widgets/speech_to_text/speech_to_text.dart @@ -12,8 +12,9 @@ import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; class SpeechToTextButton extends StatefulWidget { final TextEditingController controller; final bool mini; + final bool enabled; - const SpeechToTextButton({Key key, this.controller, this.mini = false}) : super(key: key); + const SpeechToTextButton({Key key, this.controller, this.mini = false, this.enabled = true}) : super(key: key); @override _SpeechToTextButtonState createState() => _SpeechToTextButtonState(); @@ -22,7 +23,7 @@ class SpeechToTextButton extends StatefulWidget { class _SpeechToTextButtonState extends State { bool _speechEnabled = false; SettingProvider _settingProvider; - SpeechToText _speechToText = SpeechToText(); + final SpeechToText _speechToText = SpeechToText(); /// This has to happen only once per app void _initSpeech() async { @@ -63,12 +64,15 @@ class _SpeechToTextButtonState extends State { @override void initState() { _initSpeech(); + widget.controller.addListener(() { + setState(() {}); + }); super.initState(); } @override void setState(VoidCallback fn) { - if (!this.mounted) return; + if (!mounted) return; super.setState(fn); } @@ -76,18 +80,18 @@ class _SpeechToTextButtonState extends State { Widget build(BuildContext context) { _settingProvider = Provider.of(context); return Container( - padding: EdgeInsets.only(left: 12, right: 12), + padding: const EdgeInsets.only(left: 12, right: 12), decoration: BoxDecoration( - color: Color(0xfff5f5f5), + color: const Color(0xfff5f5f5), border: Border.all( - color: Color(0xffefefef), + color: const Color(0xffefefef), ), borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), ), child: Row( children: [ - widget.mini ? SizedBox.shrink() : ASubTitle("Text To Speech"), - widget.controller.text.isNotEmpty + widget.mini ? const SizedBox.shrink() : const ASubTitle("Speech To Text"), + widget.controller.text.isNotEmpty && widget.enabled ? AIconButton2( iconData: Icons.delete, onPressed: () { @@ -95,22 +99,24 @@ class _SpeechToTextButtonState extends State { setState(() {}); }, ) - : SizedBox.shrink(), - Spacer(), + : const SizedBox.shrink(), + const Spacer(), TextButton( - onPressed: () { - if (_speechToText.isListening) return; + onPressed: widget.enabled + ? () { + if (_speechToText.isListening) return; - if (_settingProvider.speechToText == "ar") { - _settingProvider.setSpeechToText("en"); - } else { - _settingProvider.setSpeechToText("ar"); - } - }, + if (_settingProvider.speechToText == "ar") { + _settingProvider.setSpeechToText("en"); + } else { + _settingProvider.setSpeechToText("ar"); + } + } + : null, child: Text(_settingProvider.speechToText)), GestureDetector( child: _speechToText.isListening - ? Icon( + ? const Icon( Icons.fiber_manual_record, color: Colors.red, ) @@ -118,13 +124,19 @@ class _SpeechToTextButtonState extends State { Icons.mic, color: Theme.of(context).colorScheme.primary, ), - onTap: () async { - if (!_speechEnabled) { - Fluttertoast.showToast(msg: "microphone not available"); - return; - } - _startListening(); - }, + onTap: widget.enabled + ? () async { + if (!_speechEnabled) { + Fluttertoast.showToast(msg: "microphone not available"); + return; + } + if (_speechToText.isListening) { + _stopListening(); + } else { + _startListening(); + } + } + : null, ), ], ), diff --git a/lib/views/widgets/status/assistant_employee_menu.dart b/lib/views/widgets/status/assistant_employee_menu.dart new file mode 100644 index 00000000..45f2177b --- /dev/null +++ b/lib/views/widgets/status/assistant_employee_menu.dart @@ -0,0 +1,109 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/views/app_style/colors.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; + +import '../../../models/service_request/search_work_order.dart'; + +class AssistantEmployeeMenu extends StatefulWidget { + final List statuses; + final AssistantEmployees initialStatus; + final Function(AssistantEmployees) onSelect; + + const AssistantEmployeeMenu({Key key, this.statuses, this.onSelect, this.initialStatus}) : super(key: key); + + @override + _SingleAssistantEmployeeMenuState createState() => _SingleAssistantEmployeeMenuState(); +} + +class _SingleAssistantEmployeeMenuState extends State { + AssistantEmployees _selectedStatus; + + @override + void setState(VoidCallback fn) { + if (mounted) super.setState(fn); + } + + @override + void didUpdateWidget(covariant AssistantEmployeeMenu oldWidget) { + if (widget.initialStatus != null) { + final result = widget.statuses?.where((element) { + return element?.user?.id == widget.initialStatus?.user?.id; + }); + if (result.isNotEmpty) { + _selectedStatus = result.first; + } else { + _selectedStatus = null; + } + if ((widget.initialStatus?.user?.id ?? "") != (_selectedStatus?.user?.id ?? "")) { + widget.onSelect(_selectedStatus); + } + } else { + _selectedStatus = null; + } + super.didUpdateWidget(oldWidget); + } + + @override + void initState() { + if (widget.initialStatus != null) { + final result = widget.statuses?.where((element) { + return element?.user?.id == widget.initialStatus?.user?.id; + }); + if (result.isNotEmpty) _selectedStatus = result.first; + if (widget.initialStatus?.user?.id != _selectedStatus?.user?.id) { + widget.onSelect(_selectedStatus); + } + } + + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: AColors.inputFieldBackgroundColor, + border: Border.all( + color: Color(0xffefefef), + ), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + // boxShadow: const [ + // AppStyle.boxShadow + // ] + ), + child: DropdownButton( + value: _selectedStatus, + iconSize: 24, + icon: const Icon(Icons.keyboard_arrow_down_rounded), + elevation: 0, + isExpanded: true, + hint: Text( + "Select", + style: Theme.of(context).textTheme.subtitle1, + ), + style: TextStyle(color: Theme.of(context).primaryColor), + underline: const SizedBox.shrink(), + onChanged: (AssistantEmployees newValue) { + setState(() { + _selectedStatus = newValue; + }); + widget.onSelect(newValue); + }, + items: widget.statuses.map>((AssistantEmployees value) { + return DropdownMenuItem( + value: value, + child: Text( + value.user?.name ?? "NULL", + style: Theme.of(context).textTheme.titleMedium.copyWith( + color: Theme.of(context).primaryColor, + fontSize: 11, + //fontWeight: FontWeight.bold + ), + ), + ); + }).toList(), + ), + ); + } +} diff --git a/lib/views/widgets/status/employee/employee_mune.dart b/lib/views/widgets/status/employee/assigned_to_mune.dart similarity index 74% rename from lib/views/widgets/status/employee/employee_mune.dart rename to lib/views/widgets/status/employee/assigned_to_mune.dart index 5ea741d4..e07a9458 100644 --- a/lib/views/widgets/status/employee/employee_mune.dart +++ b/lib/views/widgets/status/employee/assigned_to_mune.dart @@ -1,37 +1,34 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/providers/api/status_drop_down/employee/employee_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/employee/assigned_to_provider.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/single_status_menu.dart'; -class EmployeeMenu extends StatelessWidget { + +class AssignedToMenu extends StatelessWidget { final Function(Lookup) onSelect; final Lookup initialValue; - const EmployeeMenu({Key key, this.onSelect, this.initialValue}) : super(key: key); + const AssignedToMenu({Key key, this.onSelect, this.initialValue}) : super(key: key); @override Widget build(BuildContext context) { final settingProvider = Provider.of(context); final userProvider = Provider.of(context); - final menuProvider = Provider.of(context); + final menuProvider = Provider.of(context); return LoadingManager( isLoading: menuProvider.isLoading, isFailedLoading: menuProvider.items == null, stateCode: menuProvider.stateCode, onRefresh: () async { menuProvider.reset(); - await menuProvider.getData( - user: userProvider.user, - host: settingProvider.host - ); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); }, child: SingleStatusMenu( initialStatus: initialValue, statuses: menuProvider.items, onSelect: onSelect, - ) - ); + )); } } diff --git a/lib/views/widgets/status/employee/engineers_mune.dart b/lib/views/widgets/status/employee/engineers_mune.dart new file mode 100644 index 00000000..cfd6b467 --- /dev/null +++ b/lib/views/widgets/status/employee/engineers_mune.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/employee/engineers_provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/models/engineer.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/employee/single_type_menu.dart'; + +class EngineersMenu extends StatelessWidget { + final Function(Engineer) onSelect; + final Engineer initialValue; + + const EngineersMenu({Key key, this.onSelect, this.initialValue}) : super(key: key); + @override + Widget build(BuildContext context) { + final settingProvider = Provider.of(context); + final userProvider = Provider.of(context); + final menuProvider = Provider.of(context); + return LoadingManager( + isLoading: menuProvider.isLoading, + isFailedLoading: menuProvider.items == null, + stateCode: menuProvider.stateCode, + onRefresh: () async { + menuProvider.reset(); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); + }, + child: SingleEngineerMenu( + initialStatus: initialValue, + engineers: menuProvider.items, + onSelect: onSelect, + )); + } +} diff --git a/lib/views/widgets/status/employee/single_type_menu.dart b/lib/views/widgets/status/employee/single_type_menu.dart new file mode 100644 index 00000000..30eda5bd --- /dev/null +++ b/lib/views/widgets/status/employee/single_type_menu.dart @@ -0,0 +1,87 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/models/engineer.dart'; +import 'package:test_sa/views/app_style/colors.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; + +class SingleEngineerMenu extends StatefulWidget { + final List engineers; + final Engineer initialStatus; + final Function(Engineer) onSelect; + + const SingleEngineerMenu({Key key, this.engineers, this.onSelect, this.initialStatus}) : super(key: key); + + @override + _SingleEngineerMenuState createState() => _SingleEngineerMenuState(); +} + +class _SingleEngineerMenuState extends State { + Engineer _selectedStatus; + + @override + void didUpdateWidget(covariant SingleEngineerMenu oldWidget) { + if (widget.initialStatus != null && widget.initialStatus.id != null) { + _selectedStatus = widget.engineers?.firstWhere((element) { + return element == widget.initialStatus; + }); + widget.onSelect(_selectedStatus); + } else { + _selectedStatus = null; + } + super.didUpdateWidget(oldWidget); + } + + @override + void initState() { + if (widget.initialStatus != null && widget.initialStatus.id != null) { + _selectedStatus = widget.engineers?.firstWhere((element) { + return element == widget.initialStatus; + }); + widget.onSelect(_selectedStatus); + } + + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: AColors.black), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + boxShadow: const [AppStyle.boxShadow]), + child: DropdownButton( + value: _selectedStatus, + iconSize: 24, + elevation: 16, + isExpanded: true, + hint: Text( + "Select", + style: Theme.of(context).textTheme.subtitle1, + ), + style: TextStyle(color: Theme.of(context).primaryColor), + underline: SizedBox.shrink(), + onChanged: (Engineer newValue) { + setState(() { + _selectedStatus = newValue; + }); + widget.onSelect(newValue); + }, + items: widget.engineers.map>((Engineer value) { + return DropdownMenuItem( + value: value, + child: Text( + value.name, + style: Theme.of(context).textTheme.subtitle1.copyWith( + color: Theme.of(context).primaryColor, + fontSize: 11, + //fontWeight: FontWeight.bold + ), + ), + ); + }).toList(), + ), + ); + } +} diff --git a/lib/views/widgets/status/gas_refill/gas_cylinder_size.dart b/lib/views/widgets/status/gas_refill/gas_cylinder_size.dart index 358226b0..acaec9a9 100644 --- a/lib/views/widgets/status/gas_refill/gas_cylinder_size.dart +++ b/lib/views/widgets/status/gas_refill/gas_cylinder_size.dart @@ -6,6 +6,7 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + class GasCylinderSizeMenu extends StatelessWidget { final Function(Lookup) onSelect; final Lookup initialValue; @@ -22,16 +23,12 @@ class GasCylinderSizeMenu extends StatelessWidget { stateCode: menuProvider.stateCode, onRefresh: () async { menuProvider.reset(); - await menuProvider.getData( - user: userProvider.user, - host: settingProvider.host - ); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); }, child: SingleStatusMenu( initialStatus: initialValue, statuses: menuProvider.items, onSelect: onSelect, - ) - ); + )); } } diff --git a/lib/views/widgets/status/gas_refill/gas_cylinder_type.dart b/lib/views/widgets/status/gas_refill/gas_cylinder_type.dart new file mode 100644 index 00000000..0b58d73a --- /dev/null +++ b/lib/views/widgets/status/gas_refill/gas_cylinder_type.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/gas_refill/gas_cylinder_type_provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + +class GasCylinderTypesMenu extends StatelessWidget { + final Function(Lookup) onSelect; + final Lookup initialValue; + + const GasCylinderTypesMenu({Key key, this.onSelect, this.initialValue}) : super(key: key); + @override + Widget build(BuildContext context) { + final settingProvider = Provider.of(context); + final userProvider = Provider.of(context); + final menuProvider = Provider.of(context); + return LoadingManager( + isLoading: menuProvider.isLoading, + isFailedLoading: menuProvider.items == null, + stateCode: menuProvider.stateCode, + onRefresh: () async { + menuProvider.reset(); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); + }, + child: SingleStatusMenu( + initialStatus: initialValue, + statuses: menuProvider.items, + onSelect: onSelect, + )); + } +} diff --git a/lib/views/widgets/status/gas_refill/gas_status.dart b/lib/views/widgets/status/gas_refill/gas_status.dart index 1dce0c71..7e7cbac6 100644 --- a/lib/views/widgets/status/gas_refill/gas_status.dart +++ b/lib/views/widgets/status/gas_refill/gas_status.dart @@ -6,11 +6,13 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + class GasStatusMenu extends StatelessWidget { final Function(Lookup) onSelect; final Lookup initialValue; + final bool enabled; - const GasStatusMenu({Key key, this.onSelect, this.initialValue}) : super(key: key); + const GasStatusMenu({Key key, this.enabled = true, this.onSelect, this.initialValue}) : super(key: key); @override Widget build(BuildContext context) { final settingProvider = Provider.of(context); @@ -22,16 +24,13 @@ class GasStatusMenu extends StatelessWidget { stateCode: menuProvider.stateCode, onRefresh: () async { menuProvider.reset(); - await menuProvider.getData( - user: userProvider.user, - host: settingProvider.host - ); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); }, child: SingleStatusMenu( initialStatus: initialValue, statuses: menuProvider.items, onSelect: onSelect, - ) - ); + enabled: enabled, + )); } } diff --git a/lib/views/widgets/status/gas_refill/gas_type.dart b/lib/views/widgets/status/gas_refill/gas_type.dart index 8d3b9e61..5f4c536e 100644 --- a/lib/views/widgets/status/gas_refill/gas_type.dart +++ b/lib/views/widgets/status/gas_refill/gas_type.dart @@ -6,6 +6,7 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + class GasTypeMenu extends StatelessWidget { final Function(Lookup) onSelect; final Lookup initialValue; @@ -22,16 +23,12 @@ class GasTypeMenu extends StatelessWidget { stateCode: menuProvider.stateCode, onRefresh: () async { menuProvider.reset(); - await menuProvider.getData( - user: userProvider.user, - host: settingProvider.host - ); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); }, child: SingleStatusMenu( initialStatus: initialValue, statuses: menuProvider.items, onSelect: onSelect, - ) - ); + )); } } diff --git a/lib/views/widgets/status/multi_status_menu.dart b/lib/views/widgets/status/multi_status_menu.dart index 99a52a87..50ae83bc 100644 --- a/lib/views/widgets/status/multi_status_menu.dart +++ b/lib/views/widgets/status/multi_status_menu.dart @@ -1,21 +1,21 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_typeahead/flutter_typeahead.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; + class MultiStatusMenu extends StatefulWidget { final List statuses; final List initialSelectedStatus; final Function(List) onSelect; const MultiStatusMenu({Key key, this.statuses, this.onSelect, this.initialSelectedStatus}) : super(key: key); + @override _MultiStatusMenuState createState() => _MultiStatusMenuState(); } class _MultiStatusMenuState extends State { - List _selectedStatus = []; TextEditingController _controller; @@ -31,101 +31,88 @@ class _MultiStatusMenuState extends State { _controller.clear(); super.dispose(); } + @override Widget build(BuildContext context) { - return - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Wrap( - crossAxisAlignment: WrapCrossAlignment.start, - alignment: WrapAlignment.start, - runAlignment: WrapAlignment.start, - children: List.generate( - _selectedStatus.length, - (index) { - final status = _selectedStatus[index]; - return Container( - height: 36 * AppStyle.getScaleFactor(context), - margin: EdgeInsets.all(4 * AppStyle.getScaleFactor(context)), - //padding: EdgeInsets.all(4 * AppStyle.getScaleFactor(context)), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary, - borderRadius: BorderRadius.circular(8) - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const SizedBox(width: 12,), - Text( - status.label, - style: Theme.of(context).textTheme.bodyText1.copyWith( - color:Theme.of(context).colorScheme.onPrimary, + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Wrap( + crossAxisAlignment: WrapCrossAlignment.start, + alignment: WrapAlignment.start, + runAlignment: WrapAlignment.start, + children: List.generate(_selectedStatus.length, (index) { + final status = _selectedStatus[index]; + return Container( + height: 36 * AppStyle.getScaleFactor(context), + margin: EdgeInsets.all(4 * AppStyle.getScaleFactor(context)), + //padding: EdgeInsets.all(4 * AppStyle.getScaleFactor(context)), + decoration: BoxDecoration(color: Theme.of(context).colorScheme.primary, borderRadius: BorderRadius.circular(8)), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox( + width: 12, + ), + Text( + status.name, + style: Theme.of(context).textTheme.bodyText1.copyWith( + color: Theme.of(context).colorScheme.onPrimary, ), - ), - IconButton( - color:Theme.of(context).colorScheme.onPrimary, - onPressed: (){ - _selectedStatus.remove(status); - widget.onSelect(_selectedStatus); - setState(() {}); - }, - icon: const Icon(Icons.delete) - ) - ], - ) - ); - } - ), - ), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 16 - ), - decoration: BoxDecoration( - color: Colors.white, - border: Border.all(color:AColors.black), - borderRadius: BorderRadius.circular( - AppStyle.borderRadius * AppStyle.getScaleFactor(context) - ), - boxShadow: const [ - AppStyle.boxShadow - ] - ), - child: TypeAheadField( - textFieldConfiguration: TextFieldConfiguration( - style: Theme.of(context).textTheme.subtitle1, - controller: _controller, - textAlign: TextAlign.center, - decoration: const InputDecoration( - border: InputBorder.none, - disabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - ), - textInputAction: TextInputAction.search, + ), + IconButton( + color: Theme.of(context).colorScheme.onPrimary, + onPressed: () { + _selectedStatus.remove(status); + widget.onSelect(_selectedStatus); + setState(() {}); + }, + icon: const Icon(Icons.delete)) + ], + )); + }), + ), + Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: AColors.black), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + boxShadow: const [AppStyle.boxShadow]), + child: TypeAheadField( + textFieldConfiguration: TextFieldConfiguration( + style: Theme.of(context).textTheme.subtitle1, + controller: _controller, + textAlign: TextAlign.center, + decoration: const InputDecoration( + border: InputBorder.none, + disabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, ), - suggestionsCallback: (vale) { - return widget.statuses.where((Lookup option) { - return option.label.toLowerCase().contains(_controller.text); - }); - }, - itemBuilder: (context, part) { - return ListTile( - title: Text(part.label), - ); - }, - onSuggestionSelected: (status) { - _controller.clear(); - if(!_selectedStatus.contains(status)){ - _selectedStatus.add(status); - widget.onSelect(_selectedStatus); - setState(() {}); - } - }, + textInputAction: TextInputAction.search, ), + suggestionsCallback: (vale) { + return widget.statuses.where((Lookup option) { + return option.name.toLowerCase().contains(_controller.text); + }); + }, + itemBuilder: (context, part) { + return ListTile( + title: Text(part.name), + ); + }, + onSuggestionSelected: (status) { + _controller.clear(); + if (!_selectedStatus.contains(status)) { + _selectedStatus.add(status); + widget.onSelect(_selectedStatus); + setState(() {}); + } + }, ), - ], - ); + ), + ], + ); } } diff --git a/lib/views/widgets/status/pentry/pentry_status_mune.dart b/lib/views/widgets/status/pentry/pentry_status_mune.dart index b0813f22..9f10c77c 100644 --- a/lib/views/widgets/status/pentry/pentry_status_mune.dart +++ b/lib/views/widgets/status/pentry/pentry_status_mune.dart @@ -6,6 +6,7 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + class PentryStatusMenu extends StatelessWidget { final Function(Lookup) onSelect; final Lookup initialValue; @@ -22,16 +23,12 @@ class PentryStatusMenu extends StatelessWidget { stateCode: menuProvider.stateCode, onRefresh: () async { menuProvider.reset(); - await menuProvider.getData( - user: userProvider.user, - host: settingProvider.host - ); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); }, child: SingleStatusMenu( initialStatus: initialValue, statuses: menuProvider.items, onSelect: onSelect, - ) - ); + )); } } diff --git a/lib/views/widgets/status/pentry/pentry_task_status_mune.dart b/lib/views/widgets/status/pentry/pentry_task_status_mune.dart index 8564410d..6b438dc2 100644 --- a/lib/views/widgets/status/pentry/pentry_task_status_mune.dart +++ b/lib/views/widgets/status/pentry/pentry_task_status_mune.dart @@ -6,6 +6,7 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + class PentryTaskStatusMenu extends StatelessWidget { final Function(Lookup) onSelect; final Lookup initialValue; @@ -22,16 +23,12 @@ class PentryTaskStatusMenu extends StatelessWidget { stateCode: menuProvider.stateCode, onRefresh: () async { menuProvider.reset(); - await menuProvider.getData( - user: userProvider.user, - host: settingProvider.host - ); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); }, child: SingleStatusMenu( initialStatus: initialValue, statuses: menuProvider.items, onSelect: onSelect, - ) - ); + )); } } diff --git a/lib/views/widgets/status/pentry/pentry_visit_status_mune.dart b/lib/views/widgets/status/pentry/pentry_visit_status_mune.dart index 4df17a49..d4941723 100644 --- a/lib/views/widgets/status/pentry/pentry_visit_status_mune.dart +++ b/lib/views/widgets/status/pentry/pentry_visit_status_mune.dart @@ -6,6 +6,7 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + class PentryVisitsStatusMenu extends StatelessWidget { final Function(Lookup) onSelect; final Lookup initialValue; @@ -22,16 +23,12 @@ class PentryVisitsStatusMenu extends StatelessWidget { stateCode: menuProvider.stateCode, onRefresh: () async { menuProvider.reset(); - await menuProvider.getData( - user: userProvider.user, - host: settingProvider.host - ); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); }, child: SingleStatusMenu( initialStatus: initialValue, statuses: menuProvider.items, onSelect: onSelect, - ) - ); + )); } } diff --git a/lib/views/widgets/status/report/fault_desc_menu.dart b/lib/views/widgets/status/report/fault_desc_menu.dart new file mode 100644 index 00000000..a2b670de --- /dev/null +++ b/lib/views/widgets/status/report/fault_desc_menu.dart @@ -0,0 +1,110 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/models/fault_description.dart'; +import 'package:test_sa/views/app_style/colors.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; + +class FaultDescriptionMenu extends StatefulWidget { + final List statuses; + final FaultDescription initialStatus; + final Function(FaultDescription) onSelect; + + const FaultDescriptionMenu({Key key, this.statuses, this.onSelect, this.initialStatus}) : super(key: key); + + @override + _SingleStatusMenuState createState() => _SingleStatusMenuState(); +} + +class _SingleStatusMenuState extends State { + FaultDescription _selectedStatus; + + @override + void setState(VoidCallback fn) { + if (mounted) super.setState(fn); + } + + @override + void didUpdateWidget(covariant FaultDescriptionMenu oldWidget) { + if (widget.initialStatus != null) { + final result = widget.statuses?.where((element) { + return element.id == widget.initialStatus.id; + }); + if (result.isNotEmpty) { + _selectedStatus = result.first; + } else { + _selectedStatus = null; + } + if ((widget.initialStatus?.id ?? "") != (_selectedStatus?.id ?? "")) { + widget.onSelect(_selectedStatus); + } + } else { + _selectedStatus = null; + } + super.didUpdateWidget(oldWidget); + } + + @override + void initState() { + if (widget.initialStatus != null) { + final result = widget.statuses?.where((element) { + return element.id == widget.initialStatus.id; + }); + if (result.isNotEmpty) _selectedStatus = result.first; + if (widget.initialStatus.id != _selectedStatus?.id) { + widget.onSelect(_selectedStatus); + } + } + + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: AColors.inputFieldBackgroundColor, + border: Border.all( + color: Color(0xffefefef), + ), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + // boxShadow: const [ + // AppStyle.boxShadow + // ] + ), + child: DropdownButton( + value: _selectedStatus, + iconSize: 24, + icon: const Icon(Icons.keyboard_arrow_down_rounded), + elevation: 0, + isExpanded: true, + hint: Text( + "Select", + style: Theme.of(context).textTheme.subtitle1, + ), + style: TextStyle(color: Theme.of(context).primaryColor), + underline: SizedBox.shrink(), + onChanged: (FaultDescription newValue) { + setState(() { + _selectedStatus = newValue; + }); + widget.onSelect(newValue); + }, + items: widget.statuses.map>( + (FaultDescription value) { + return DropdownMenuItem( + value: value, + child: Text( + value.defectName ?? "", + style: Theme.of(context).textTheme.subtitle1.copyWith( + color: Theme.of(context).primaryColor, + fontSize: 11, + //fontWeight: FontWeight.bold + ), + ), + ); + }, + ).toList(), + ), + ); + } +} diff --git a/lib/views/widgets/status/report/service_report_all_users.dart b/lib/views/widgets/status/report/service_report_all_users.dart new file mode 100644 index 00000000..c3098096 --- /dev/null +++ b/lib/views/widgets/status/report/service_report_all_users.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_users_provider.dart'; +import 'package:test_sa/models/engineer.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/users_menu.dart'; + +class ServiceReportAllUsers extends StatelessWidget { + final Function(Engineer) onSelect; + final Engineer initialValue; + const ServiceReportAllUsers({Key key, @required this.onSelect, this.initialValue}) : super(key: key); + @override + Widget build(BuildContext context) { + ServiceReportUsersProvider menuProvider = Provider.of(context); + return LoadingManager( + isLoading: menuProvider.isLoading, + isFailedLoading: menuProvider.engineers == null, + stateCode: menuProvider.stateCode, + onRefresh: () async { + menuProvider.getAllUsers(); + }, + child: UsersMenu( + initialStatus: initialValue, + statuses: menuProvider.engineers, + onSelect: onSelect, + ), + ); + } +} diff --git a/lib/views/widgets/status/report/service_report_assistant_employee_menu.dart b/lib/views/widgets/status/report/service_report_assistant_employee_menu.dart new file mode 100644 index 00000000..1bf2c491 --- /dev/null +++ b/lib/views/widgets/status/report/service_report_assistant_employee_menu.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/models/service_request/search_work_order.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/assistant_employee_menu.dart'; + +import '../../../../controllers/providers/api/status_drop_down/report/service_report_assistants_employee_provider.dart'; + +class ServiceReportAssistantEmployeeMenu extends StatelessWidget { + final Function(AssistantEmployees) onSelect; + final AssistantEmployees initialValue; + const ServiceReportAssistantEmployeeMenu({Key key, @required this.onSelect, this.initialValue}) : super(key: key); + @override + Widget build(BuildContext context) { + ServiceReportAssistantsEmployeeProvider menuProvider = Provider.of(context); + return LoadingManager( + isLoading: menuProvider.isLoading, + isFailedLoading: menuProvider.assistantEmployees == null, + stateCode: menuProvider.stateCode, + onRefresh: () async { + await menuProvider.getAssistantEmployees(); + }, + child: AssistantEmployeeMenu( + initialStatus: initialValue, + statuses: menuProvider.assistantEmployees, + onSelect: onSelect, + ), + ); + } +} diff --git a/lib/views/widgets/status/report/service_report_equipment_status.dart b/lib/views/widgets/status/report/service_report_equipment_status.dart new file mode 100644 index 00000000..63f9dfc0 --- /dev/null +++ b/lib/views/widgets/status/report/service_report_equipment_status.dart @@ -0,0 +1,76 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_equipment_status_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/service_report.dart'; +import 'package:test_sa/models/service_request/service_request.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + +class ServiceReportEquipmentStatusMenu extends StatefulWidget { + final Function(Lookup) onSelect; + final ServiceReport report; + final ServiceRequest request; + + const ServiceReportEquipmentStatusMenu({Key key, this.onSelect, this.report, this.request}) : super(key: key); + + @override + State createState() => _ServiceReportEquipmentStatusMenuState(); +} + +class _ServiceReportEquipmentStatusMenuState extends State { + bool firstTime = true; + @override + Widget build(BuildContext context) { + SettingProvider settingProvider = Provider.of(context); + UserProvider userProvider = Provider.of(context); + ServiceReportEquipmentStatusProvider menuProvider = Provider.of(context); + ServiceReportLastCallsProvider callsLastSituationsProvider = Provider.of(context); + if (firstTime) { + callsLastSituationsProvider.reset(); + + firstTime = false; + } + return LoadingManager( + isLoading: menuProvider.isLoading == true || callsLastSituationsProvider.isLoading == true, + isFailedLoading: menuProvider.statuses == null || callsLastSituationsProvider.calls == null, + stateCode: menuProvider.stateCode == null || callsLastSituationsProvider.stateCode == null ? null : max(menuProvider.stateCode ?? 0, callsLastSituationsProvider.stateCode ?? 0), + onRefresh: () async { + await callsLastSituationsProvider.getCalls( + user: userProvider.user, + host: settingProvider.host, + serviceStatus: widget.report?.equipmentStatus?.id, + typeName: widget.report?.type?.name, + id: widget.report?.id, + woId: widget.request?.id, + ); + if (menuProvider.stateCode == null) { + menuProvider.reset(); + await menuProvider.getTypes(user: userProvider.user, host: settingProvider.host); + setState(() {}); + } + }, + child: SingleStatusMenu( + statuses: menuProvider.statuses, + initialStatus: widget.report?.equipmentStatus, + onSelect: (status) { + widget.report?.callLastSituation = null; + callsLastSituationsProvider.getCalls( + user: userProvider.user, + host: settingProvider.host, + serviceStatus: status?.id, + id: widget.report?.id, + woId: widget.request?.id, + typeName: widget.report?.type?.name, + ); + + widget.onSelect(status); + }, + )); + } +} diff --git a/lib/views/widgets/status/report/service_report_fault_description.dart b/lib/views/widgets/status/report/service_report_fault_description.dart new file mode 100644 index 00000000..facda9dd --- /dev/null +++ b/lib/views/widgets/status/report/service_report_fault_description.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_fault_description_provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/models/fault_description.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/report/fault_desc_menu.dart'; + +import '../../app_text_form_field.dart'; + +class ServiceReportFaultDescription extends StatelessWidget { + final String requestId; + final Function(FaultDescription) onSelect; + final FaultDescription initialValue; + final bool enabled; + + const ServiceReportFaultDescription({Key key, this.requestId, this.onSelect, this.initialValue, this.enabled = true}) : super(key: key); + @override + Widget build(BuildContext context) { + SettingProvider settingProvider = Provider.of(context); + UserProvider userProvider = Provider.of(context); + ServiceRequestFaultDescriptionProvider menuProvider = Provider.of(context); + return LoadingManager( + isLoading: menuProvider.isLoading, + isFailedLoading: menuProvider.items == null, + stateCode: menuProvider.stateCode, + onRefresh: () async { + menuProvider.reset(); + await menuProvider.getCallRequestForWorkOrder(user: userProvider.user, host: settingProvider.host, requestId: requestId); + }, + child: ((menuProvider.items?.isEmpty ?? true) || (!enabled)) + ? ATextFormField( + initialValue: (!enabled) ? initialValue?.defectName ?? "" : "", + enable: false, + ) + : FaultDescriptionMenu( + initialStatus: initialValue, + statuses: menuProvider.items, + onSelect: onSelect, + ), + ); + } +} diff --git a/lib/views/widgets/status/report/service_report_last_call.dart b/lib/views/widgets/status/report/service_report_last_call.dart index a3f59211..10919fb8 100644 --- a/lib/views/widgets/status/report/service_report_last_call.dart +++ b/lib/views/widgets/status/report/service_report_last_call.dart @@ -5,15 +5,17 @@ import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/service_report.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + class ServiceReportLastCallsMenu extends StatelessWidget { final Function(Lookup) onSelect; final ServiceReport report; - const ServiceReportLastCallsMenu({ - Key key,@required this.onSelect,@required this.report}) : super(key: key); + const ServiceReportLastCallsMenu({Key key, @required this.onSelect, @required this.report}) : super(key: key); + @override Widget build(BuildContext context) { ServiceReportLastCallsProvider _menuProvider = Provider.of(context); + print("report?.callLastSituation:${report?.callLastSituation?.toMap()}"); return LoadingManager( isLoading: _menuProvider.isLoading, isFailedLoading: _menuProvider.calls == null, @@ -23,7 +25,6 @@ class ServiceReportLastCallsMenu extends StatelessWidget { initialStatus: report?.callLastSituation, statuses: _menuProvider.calls, onSelect: onSelect, - ) - ); + )); } } diff --git a/lib/views/widgets/status/report/service_report_maintenance_situation.dart b/lib/views/widgets/status/report/service_report_maintenance_situation.dart new file mode 100644 index 00000000..311581a0 --- /dev/null +++ b/lib/views/widgets/status/report/service_report_maintenance_situation.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_maintenance_situation_provider.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + +class ServiceReportMaintenanceSituation extends StatelessWidget { + final Function(Lookup) onSelect; + final Lookup initialValue; + final String woId; + + const ServiceReportMaintenanceSituation({ + Key key, + @required this.onSelect, + @required this.initialValue, + @required this.woId, + }) : super(key: key); + @override + Widget build(BuildContext context) { + ServiceReportMaintenanceSituationProvider menuProvider = Provider.of(context); + return LoadingManager( + isLoading: menuProvider.isLoading, + isFailedLoading: menuProvider.operators == null, + stateCode: menuProvider.stateCode, + onRefresh: () async { + menuProvider.getOperators(woId); + }, + child: SingleStatusMenu( + initialStatus: initialValue, + statuses: menuProvider.operators, + onSelect: onSelect, + ), + ); + } +} diff --git a/lib/views/widgets/status/report/service_report_reasons.dart b/lib/views/widgets/status/report/service_report_reasons.dart index dbdd48ef..81092b5c 100644 --- a/lib/views/widgets/status/report/service_report_reasons.dart +++ b/lib/views/widgets/status/report/service_report_reasons.dart @@ -6,11 +6,13 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + class ServiceReportReasonsMenu extends StatelessWidget { final Lookup initialValue; final Function(Lookup) onSelect; const ServiceReportReasonsMenu({Key key, this.onSelect, this.initialValue}) : super(key: key); + @override Widget build(BuildContext context) { SettingProvider _settingProvider = Provider.of(context); @@ -25,14 +27,12 @@ class ServiceReportReasonsMenu extends StatelessWidget { await _menuProvider.getTypes( user: _userProvider.user, host: _settingProvider.host, - ); }, child: SingleStatusMenu( initialStatus: initialValue, statuses: _menuProvider.reasons, onSelect: onSelect, - ) - ); + )); } } diff --git a/lib/views/widgets/status/report/service_report_repair_location.dart b/lib/views/widgets/status/report/service_report_repair_location.dart new file mode 100644 index 00000000..52cb3038 --- /dev/null +++ b/lib/views/widgets/status/report/service_report_repair_location.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_repair_location_provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + +class ServiceReportRepairLocation extends StatelessWidget { + final Lookup initialValue; + final Function(Lookup) onSelect; + + const ServiceReportRepairLocation({Key key, this.onSelect, this.initialValue}) : super(key: key); + + @override + Widget build(BuildContext context) { + SettingProvider _settingProvider = Provider.of(context); + UserProvider _userProvider = Provider.of(context); + ServiceReportRepairLocationProvider _menuProvider = Provider.of(context); + return LoadingManager( + isLoading: _menuProvider.isLoading, + isFailedLoading: _menuProvider.reasons == null, + stateCode: _menuProvider.stateCode, + onRefresh: () async { + _menuProvider.reset(); + await _menuProvider.getTypes( + user: _userProvider.user, + host: _settingProvider.host, + ); + }, + child: SingleStatusMenu( + initialStatus: initialValue, + statuses: _menuProvider.reasons, + onSelect: onSelect, + )); + } +} diff --git a/lib/views/widgets/status/report/service_report_status.dart b/lib/views/widgets/status/report/service_report_status.dart index 8a4d1c98..b21057cb 100644 --- a/lib/views/widgets/status/report/service_report_status.dart +++ b/lib/views/widgets/status/report/service_report_status.dart @@ -8,13 +8,16 @@ import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/service_report.dart'; +import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + class ServiceReportStatusMenu extends StatefulWidget { final Function(Lookup) onSelect; final ServiceReport report; + final ServiceRequest request; - const ServiceReportStatusMenu({Key key, this.onSelect, this.report}) : super(key: key); + const ServiceReportStatusMenu({Key key, this.onSelect, this.report, this.request}) : super(key: key); @override State createState() => _ServiceReportStatusMenuState(); @@ -24,47 +27,50 @@ class _ServiceReportStatusMenuState extends State { bool firstTime = true; @override Widget build(BuildContext context) { - SettingProvider _settingProvider = Provider.of(context); - UserProvider _userProvider = Provider.of(context); - ServiceReportStatusProvider _menuProvider = Provider.of(context); - ServiceReportLastCallsProvider _callsLastSituationsProvider = Provider.of(context,listen: false); - if(firstTime){ - _callsLastSituationsProvider.reset(); + SettingProvider settingProvider = Provider.of(context); + UserProvider userProvider = Provider.of(context); + ServiceReportStatusProvider menuProvider = Provider.of(context); + ServiceReportLastCallsProvider callsLastSituationsProvider = Provider.of(context); + if (firstTime) { + callsLastSituationsProvider.reset(); firstTime = false; } return LoadingManager( - isLoading: _menuProvider.isLoading == true || _callsLastSituationsProvider.isLoading == true, - isFailedLoading: _menuProvider.statuses == null || _callsLastSituationsProvider.calls == null, - stateCode: _menuProvider.stateCode == null || _callsLastSituationsProvider.stateCode == null ? null: - max(_menuProvider.stateCode ?? 0,_callsLastSituationsProvider.stateCode ?? 0), + isLoading: menuProvider.isLoading == true || callsLastSituationsProvider.isLoading == true, + isFailedLoading: menuProvider.statuses == null || callsLastSituationsProvider.calls == null, + stateCode: menuProvider.stateCode == null || callsLastSituationsProvider.stateCode == null ? null : max(menuProvider.stateCode ?? 0, callsLastSituationsProvider.stateCode ?? 0), onRefresh: () async { - if(_menuProvider.stateCode == null){ - _menuProvider.reset(); - await _menuProvider.getTypes( - user: _userProvider.user, - host: _settingProvider.host - ); - } - await _callsLastSituationsProvider.getCalls( - user: _userProvider.user, - host: _settingProvider.host, - serviceStatus: widget.report.status?.id.toString() + await callsLastSituationsProvider.getCalls( + user: userProvider.user, + host: settingProvider.host, + serviceStatus: widget.report.equipmentStatus?.id, + typeName: widget.report.type?.name, + id: widget.report.id, + woId: widget.request.id, ); + if (menuProvider.stateCode == null) { + menuProvider.reset(); + await menuProvider.getTypes(user: userProvider.user, host: settingProvider.host); + setState(() {}); + } }, child: SingleStatusMenu( - statuses: _menuProvider.statuses, - initialStatus: widget.report.status, - onSelect: (status){ - _callsLastSituationsProvider.getCalls( - user: _userProvider.user, - host: _settingProvider.host, - serviceStatus: status.id.toString() - ); + statuses: menuProvider.statuses, + initialStatus: widget.report.equipmentStatus, + onSelect: (status) { widget.report.callLastSituation = null; + callsLastSituationsProvider.getCalls( + user: userProvider.user, + host: settingProvider.host, + serviceStatus: status.id, + id: widget.report.id, + woId: widget.request.id, + typeName: widget.report.type?.name, + ); + widget.onSelect(status); }, - ) - ); + )); } } diff --git a/lib/views/widgets/status/report/service_report_type.dart b/lib/views/widgets/status/report/service_report_type.dart index fb315747..99f66397 100644 --- a/lib/views/widgets/status/report/service_report_type.dart +++ b/lib/views/widgets/status/report/service_report_type.dart @@ -6,6 +6,7 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + class ServiceReportTypeMenu extends StatelessWidget { final Function(Lookup) onSelect; final Lookup initialValue; @@ -22,17 +23,13 @@ class ServiceReportTypeMenu extends StatelessWidget { stateCode: menuProvider.stateCode, onRefresh: () async { menuProvider.reset(); - await menuProvider.getTypes( - user: userProvider.user, - host: settingProvider.host - ); + await menuProvider.getTypes(user: userProvider.user, host: settingProvider.host); onSelect(initialValue ?? menuProvider.types?.last); }, child: SingleStatusMenu( initialStatus: initialValue ?? menuProvider.types?.last, statuses: menuProvider.types, onSelect: onSelect, - ) - ); + )); } } diff --git a/lib/views/widgets/status/report/service_report_visit_date_operator.dart b/lib/views/widgets/status/report/service_report_visit_date_operator.dart new file mode 100644 index 00000000..5148ffaa --- /dev/null +++ b/lib/views/widgets/status/report/service_report_visit_date_operator.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_visit_date_operator_provider.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + +class ServiceReportVisitDateOperator extends StatelessWidget { + final Function(Lookup) onSelect; + final Lookup initialValue; + + const ServiceReportVisitDateOperator({Key key, @required this.onSelect, @required this.initialValue}) : super(key: key); + @override + Widget build(BuildContext context) { + ServiceReportVisitOperatorProvider menuProvider = Provider.of(context); + return LoadingManager( + isLoading: menuProvider.isLoading, + isFailedLoading: menuProvider.operators == null, + stateCode: menuProvider.stateCode, + onRefresh: () async { + menuProvider.getOperators(); + }, + child: SingleStatusMenu( + initialStatus: initialValue, + statuses: menuProvider.operators, + onSelect: onSelect, + ), + ); + } +} diff --git a/lib/views/widgets/status/report/service_status.dart b/lib/views/widgets/status/report/service_status.dart index 37eb554e..99c968c0 100644 --- a/lib/views/widgets/status/report/service_status.dart +++ b/lib/views/widgets/status/report/service_status.dart @@ -6,11 +6,13 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/single_status_menu.dart'; -class ServiceStatusMenu extends StatelessWidget { + +class ServiceAssetTypeMenu extends StatelessWidget { final Function(Lookup) onSelect; final Lookup initialValue; - const ServiceStatusMenu({Key key, this.onSelect, this.initialValue}) : super(key: key); + const ServiceAssetTypeMenu({Key key, this.onSelect, this.initialValue}) : super(key: key); + @override Widget build(BuildContext context) { SettingProvider _settingProvider = Provider.of(context); @@ -22,16 +24,12 @@ class ServiceStatusMenu extends StatelessWidget { stateCode: _menuProvider.stateCode, onRefresh: () async { _menuProvider.reset(); - await _menuProvider.getTypes( - user: _userProvider.user, - host: _settingProvider.host - ); + await _menuProvider.getTypes(user: _userProvider.user, host: _settingProvider.host); }, child: SingleStatusMenu( initialStatus: initialValue, statuses: _menuProvider.statuses, onSelect: onSelect, - ) - ); + )); } } diff --git a/lib/views/widgets/status/service_request/service_request_defect_types_mune.dart b/lib/views/widgets/status/service_request/service_request_defect_types_mune.dart index be02c54e..3496f3c0 100644 --- a/lib/views/widgets/status/service_request/service_request_defect_types_mune.dart +++ b/lib/views/widgets/status/service_request/service_request_defect_types_mune.dart @@ -6,11 +6,14 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + class ServiceRequestDefectTypesMenu extends StatelessWidget { final Function(Lookup) onSelect; final Lookup initialValue; + final bool enabled; + + const ServiceRequestDefectTypesMenu({Key key, this.onSelect, this.initialValue, this.enabled = true}) : super(key: key); - const ServiceRequestDefectTypesMenu({Key key, this.onSelect, this.initialValue}) : super(key: key); @override Widget build(BuildContext context) { final settingProvider = Provider.of(context); @@ -22,16 +25,13 @@ class ServiceRequestDefectTypesMenu extends StatelessWidget { stateCode: menuProvider.stateCode, onRefresh: () async { menuProvider.reset(); - await menuProvider.getData( - user: userProvider.user, - host: settingProvider.host - ); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); }, child: SingleStatusMenu( initialStatus: initialValue, statuses: menuProvider.items, onSelect: onSelect, - ) - ); + enabled: enabled, + )); } } diff --git a/lib/views/widgets/status/service_request/service_request_first_action.dart b/lib/views/widgets/status/service_request/service_request_first_action.dart new file mode 100644 index 00000000..02c5f94e --- /dev/null +++ b/lib/views/widgets/status/service_request/service_request_first_action.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + +import '../../../../controllers/providers/api/status_drop_down/service_reqest/service_request_first_action_provider.dart'; + +class ServiceRequestedFirstAction extends StatelessWidget { + final Function(Lookup) onSelect; + final Lookup initialValue; + + const ServiceRequestedFirstAction({Key key, this.onSelect, this.initialValue}) : super(key: key); + @override + Widget build(BuildContext context) { + final settingProvider = Provider.of(context); + final userProvider = Provider.of(context); + final menuProvider = Provider.of(context); + return LoadingManager( + isLoading: menuProvider.isLoading, + isFailedLoading: menuProvider.items == null, + stateCode: menuProvider.stateCode, + onRefresh: () async { + menuProvider.reset(); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); + }, + child: SingleStatusMenu( + initialStatus: initialValue, + statuses: menuProvider.items, + onSelect: onSelect, + ), + ); + } +} diff --git a/lib/views/widgets/status/service_request/service_request_loan_availability.dart b/lib/views/widgets/status/service_request/service_request_loan_availability.dart new file mode 100644 index 00000000..31cb3f33 --- /dev/null +++ b/lib/views/widgets/status/service_request/service_request_loan_availability.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + +import '../../../../controllers/providers/api/status_drop_down/service_reqest/service_request_loan_availability_provider.dart'; + +class ServiceRequestedLoanAvailability extends StatelessWidget { + final Function(Lookup) onSelect; + final Lookup initialValue; + + const ServiceRequestedLoanAvailability({Key key, this.onSelect, this.initialValue}) : super(key: key); + @override + Widget build(BuildContext context) { + final settingProvider = Provider.of(context); + final userProvider = Provider.of(context); + final menuProvider = Provider.of(context); + return LoadingManager( + isLoading: menuProvider.isLoading, + isFailedLoading: menuProvider.items == null, + stateCode: menuProvider.stateCode, + onRefresh: () async { + menuProvider.reset(); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); + }, + child: SingleStatusMenu( + initialStatus: initialValue, + statuses: menuProvider.items, + onSelect: onSelect, + )); + } +} diff --git a/lib/views/widgets/status/service_request/service_request_priority_mune.dart b/lib/views/widgets/status/service_request/service_request_priority_mune.dart index fe3bd6db..7cd90242 100644 --- a/lib/views/widgets/status/service_request/service_request_priority_mune.dart +++ b/lib/views/widgets/status/service_request/service_request_priority_mune.dart @@ -6,32 +6,32 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + class ServiceRequestPriorityMenu extends StatelessWidget { final Function(Lookup) onSelect; final Lookup initialValue; + final bool enabled; - const ServiceRequestPriorityMenu({Key key, this.onSelect, this.initialValue}) : super(key: key); + const ServiceRequestPriorityMenu({Key key, this.onSelect, this.initialValue, this.enabled}) : super(key: key); @override Widget build(BuildContext context) { final settingProvider = Provider.of(context); final userProvider = Provider.of(context); final menuProvider = Provider.of(context); + return LoadingManager( isLoading: menuProvider.isLoading, isFailedLoading: menuProvider.items == null, stateCode: menuProvider.stateCode, onRefresh: () async { menuProvider.reset(); - await menuProvider.getData( - user: userProvider.user, - host: settingProvider.host - ); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); }, child: SingleStatusMenu( initialStatus: initialValue, statuses: menuProvider.items, onSelect: onSelect, - ) - ); + enabled: enabled, + )); } } diff --git a/lib/views/widgets/status/service_request/service_request_status_mune.dart b/lib/views/widgets/status/service_request/service_request_status_mune.dart new file mode 100644 index 00000000..4cb7f730 --- /dev/null +++ b/lib/views/widgets/status/service_request/service_request_status_mune.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/service_reqest/service_request_status_provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + +class ServiceRequestStatusMenu extends StatelessWidget { + final Function(Lookup) onSelect; + final Lookup initialValue; + + const ServiceRequestStatusMenu({Key key, this.onSelect, this.initialValue}) : super(key: key); + @override + Widget build(BuildContext context) { + final settingProvider = Provider.of(context); + final userProvider = Provider.of(context); + final menuProvider = Provider.of(context); + return LoadingManager( + isLoading: menuProvider.isLoading, + isFailedLoading: menuProvider.items == null, + stateCode: menuProvider.stateCode, + onRefresh: () async { + menuProvider.reset(); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); + }, + child: SingleStatusMenu( + initialStatus: initialValue, + statuses: menuProvider.items, + onSelect: onSelect, + )); + } +} diff --git a/lib/views/widgets/status/service_request/service_request_through_mune.dart b/lib/views/widgets/status/service_request/service_request_through_mune.dart new file mode 100644 index 00000000..1a735dc8 --- /dev/null +++ b/lib/views/widgets/status/service_request/service_request_through_mune.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/service_reqest/service_request_through_provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + +class ServiceRequestedThroughMenu extends StatelessWidget { + final Function(Lookup) onSelect; + final Lookup initialValue; + final bool enabled; + + const ServiceRequestedThroughMenu({Key key, this.onSelect, this.initialValue, this.enabled = true}) : super(key: key); + @override + Widget build(BuildContext context) { + final settingProvider = Provider.of(context); + final userProvider = Provider.of(context); + final menuProvider = Provider.of(context); + return LoadingManager( + isLoading: menuProvider.isLoading, + isFailedLoading: menuProvider.items == null, + stateCode: menuProvider.stateCode, + onRefresh: () async { + menuProvider.reset(); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); + }, + child: SingleStatusMenu( + initialStatus: enabled ? initialValue : menuProvider.getDefaultItem(), + statuses: menuProvider.items, + onSelect: onSelect, + enabled: enabled, + )); + } +} diff --git a/lib/views/widgets/status/service_request/service_request_types_mune.dart b/lib/views/widgets/status/service_request/service_request_types_mune.dart new file mode 100644 index 00000000..4f5e34a7 --- /dev/null +++ b/lib/views/widgets/status/service_request/service_request_types_mune.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/service_reqest/service_request_type_provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + +class ServiceRequestTypesMenu extends StatelessWidget { + final Function(Lookup) onSelect; + final Lookup initialValue; + final bool enabled; + final bool withDefaultItem; + + const ServiceRequestTypesMenu({Key key, this.onSelect, this.initialValue, this.withDefaultItem = false, this.enabled = true}) : super(key: key); + @override + Widget build(BuildContext context) { + final settingProvider = Provider.of(context); + final userProvider = Provider.of(context); + final menuProvider = Provider.of(context); + return LoadingManager( + isLoading: menuProvider.isLoading, + isFailedLoading: menuProvider.items == null, + stateCode: menuProvider.stateCode, + onRefresh: () async { + menuProvider.reset(); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); + }, + child: SingleStatusMenu( + initialStatus: (enabled || !withDefaultItem) ? initialValue : menuProvider.getDefaultItem(), + statuses: menuProvider.items, + enabled: enabled, + onSelect: onSelect, + ), + ); + } +} diff --git a/lib/views/widgets/status/single_status_menu.dart b/lib/views/widgets/status/single_status_menu.dart index 212cd1c8..6a9a9908 100644 --- a/lib/views/widgets/status/single_status_menu.dart +++ b/lib/views/widgets/status/single_status_menu.dart @@ -7,8 +7,9 @@ class SingleStatusMenu extends StatefulWidget { final List statuses; final Lookup initialStatus; final Function(Lookup) onSelect; + final bool enabled; - const SingleStatusMenu({Key key, this.statuses, this.onSelect, this.initialStatus}) : super(key: key); + const SingleStatusMenu({Key key, this.enabled = true, this.statuses, this.onSelect, this.initialStatus}) : super(key: key); @override _SingleStatusMenuState createState() => _SingleStatusMenuState(); @@ -17,12 +18,25 @@ class SingleStatusMenu extends StatefulWidget { class _SingleStatusMenuState extends State { Lookup _selectedStatus; + @override + void setState(VoidCallback fn) { + if (mounted) super.setState(fn); + } + @override void didUpdateWidget(covariant SingleStatusMenu oldWidget) { if (widget.initialStatus != null) { - _selectedStatus = widget.statuses?.firstWhere((element) { - return element?.id == widget.initialStatus.id; + final result = widget.statuses?.where((element) { + return element == widget.initialStatus; }); + if (result.isNotEmpty) { + _selectedStatus = result.first; + } else { + _selectedStatus = null; + } + if ((widget.initialStatus?.id ?? "") != (_selectedStatus?.id ?? "")) { + widget.onSelect(_selectedStatus); + } } else { _selectedStatus = null; } @@ -32,9 +46,13 @@ class _SingleStatusMenuState extends State { @override void initState() { if (widget.initialStatus != null) { - _selectedStatus = widget.statuses?.firstWhere((element) { - return element?.id == widget.initialStatus.id; + final result = widget.statuses?.where((element) { + return element == widget.initialStatus; }); + if (result.isNotEmpty) _selectedStatus = result.first; + if (widget.initialStatus.id != _selectedStatus?.id) { + widget.onSelect(_selectedStatus); + } } super.initState(); @@ -57,7 +75,7 @@ class _SingleStatusMenuState extends State { child: DropdownButton( value: _selectedStatus, iconSize: 24, - icon: Icon(Icons.keyboard_arrow_down_rounded), + icon: const Icon(Icons.keyboard_arrow_down_rounded), elevation: 0, isExpanded: true, hint: Text( @@ -65,19 +83,25 @@ class _SingleStatusMenuState extends State { style: Theme.of(context).textTheme.subtitle1, ), style: TextStyle(color: Theme.of(context).primaryColor), - underline: SizedBox.shrink(), - onChanged: (Lookup newValue) { - setState(() { - _selectedStatus = newValue; - }); - widget.onSelect(newValue); - }, + underline: const SizedBox.shrink(), + onChanged: widget.enabled == false + ? null + : (Lookup newValue) { + setState(() { + _selectedStatus = newValue; + }); + widget.onSelect(newValue); + }, items: widget.statuses.map>((Lookup value) { return DropdownMenuItem( value: value, child: Text( - value.label, - style: Theme.of(context).textTheme.subtitle1.copyWith(color: Theme.of(context).primaryColor, fontWeight: FontWeight.w600), + value.name, + style: Theme.of(context).textTheme.subtitle1.copyWith( + color: widget.enabled ? Theme.of(context).primaryColor : Colors.grey, + fontSize: 11, + //fontWeight: FontWeight.bold + ), ), ); }).toList(), diff --git a/lib/views/widgets/status/users_menu.dart b/lib/views/widgets/status/users_menu.dart new file mode 100644 index 00000000..8ffad745 --- /dev/null +++ b/lib/views/widgets/status/users_menu.dart @@ -0,0 +1,109 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/views/app_style/colors.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; + +import '../../../models/engineer.dart'; + +class UsersMenu extends StatefulWidget { + final List statuses; + final Engineer initialStatus; + final Function(Engineer) onSelect; + + const UsersMenu({Key key, this.statuses, this.onSelect, this.initialStatus}) : super(key: key); + + @override + _SingleUsersMenuState createState() => _SingleUsersMenuState(); +} + +class _SingleUsersMenuState extends State { + Engineer _selectedStatus; + + @override + void setState(VoidCallback fn) { + if (mounted) super.setState(fn); + } + + @override + void didUpdateWidget(covariant UsersMenu oldWidget) { + if (widget.initialStatus != null) { + final result = widget.statuses?.where((element) { + return element == widget.initialStatus; + }); + if (result.isNotEmpty) { + _selectedStatus = result.first; + } else { + _selectedStatus = null; + } + if ((widget.initialStatus?.id ?? "") != (_selectedStatus?.id ?? "")) { + widget.onSelect(_selectedStatus); + } + } else { + _selectedStatus = null; + } + super.didUpdateWidget(oldWidget); + } + + @override + void initState() { + if (widget.initialStatus != null) { + final result = widget.statuses?.where((element) { + return element == widget.initialStatus; + }); + if (result.isNotEmpty) _selectedStatus = result.first; + if (widget.initialStatus.id != _selectedStatus?.id) { + widget.onSelect(_selectedStatus); + } + } + + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: AColors.inputFieldBackgroundColor, + border: Border.all( + color: Color(0xffefefef), + ), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + // boxShadow: const [ + // AppStyle.boxShadow + // ] + ), + child: DropdownButton( + value: _selectedStatus, + iconSize: 24, + icon: const Icon(Icons.keyboard_arrow_down_rounded), + elevation: 0, + isExpanded: true, + hint: Text( + "Select", + style: Theme.of(context).textTheme.subtitle1, + ), + style: TextStyle(color: Theme.of(context).primaryColor), + underline: SizedBox.shrink(), + onChanged: (Engineer newValue) { + setState(() { + _selectedStatus = newValue; + }); + widget.onSelect(newValue); + }, + items: widget.statuses.map>((Engineer value) { + return DropdownMenuItem( + value: value, + child: Text( + value.name, + style: Theme.of(context).textTheme.subtitle1.copyWith( + color: Theme.of(context).primaryColor, + fontSize: 11, + //fontWeight: FontWeight.bold + ), + ), + ); + }).toList(), + ), + ); + } +} diff --git a/lib/views/widgets/switch_button.dart b/lib/views/widgets/switch_button.dart new file mode 100644 index 00000000..ccab66a4 --- /dev/null +++ b/lib/views/widgets/switch_button.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; + +import '../app_style/colors.dart'; +import '../app_style/sizing.dart'; + +class ASwitchButton extends StatelessWidget { + final String title; + final bool value; + final void Function(bool) onChange; + + const ASwitchButton({ + @required this.title, + @required this.value, + @required this.onChange, + Key key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + margin: const EdgeInsets.symmetric(vertical: 8), + decoration: BoxDecoration( + color: AColors.inputFieldBackgroundColor, + border: Border.all( + color: const Color(0xffefefef), + ), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ASubTitle(title), + Switch.adaptive( + value: value, + activeColor: AColors.primaryColor, + onChanged: onChange, + ), + ], + ), + ); + } +} diff --git a/lib/views/widgets/timer/app_timer.dart b/lib/views/widgets/timer/app_timer.dart index 95f4fbe7..fdfe2483 100644 --- a/lib/views/widgets/timer/app_timer.dart +++ b/lib/views/widgets/timer/app_timer.dart @@ -4,16 +4,19 @@ import 'package:flutter/material.dart'; import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; -import 'package:test_sa/views/widgets/loaders/app_loading.dart'; + class AppTimer extends StatefulWidget { final TimerModel timer; final Future Function(TimerModel) onChange; final TextStyle style; + final bool enabled; + const AppTimer({ Key key, this.timer, this.onChange, this.style, + this.enabled = true, }) : super(key: key); @override @@ -27,17 +30,16 @@ class _AppTimerState extends State { int _delay = 0; bool _running = false; bool _loading = false; - final ValueNotifier _period = ValueNotifier("0:00:00"); + final ValueNotifier _period = ValueNotifier("0:00:00"); _startTimer() async { if (!_running) { final time = DateTime.now(); - bool result = await widget.onChange( - TimerModel(startAt: time,endAt: null,durationInSecond: _delay)); - if(!result) return; + bool result = await widget.onChange(TimerModel(startAt: time, endAt: null, durationInSecond: _delay)); + if (!result) return; _running = true; - if(_endAt != null){ + if (_endAt != null) { _delay += _endAt.difference(_startAt).inSeconds; } _startAt = time.subtract(Duration(seconds: _delay)); @@ -45,19 +47,16 @@ class _AppTimerState extends State { } _timer = Timer.periodic(const Duration(seconds: 1), (timer) { - if(_loading == true) return; - _period.value = (_endAt ?? DateTime.now()).difference( - _startAt - ).toString().split(".").first; + if (_loading == true) return; + _period.value = (_endAt ?? DateTime.now()).difference(_startAt).toString().split(".").first; }); } _stopTimer() async { final time = DateTime.now(); final tempStartAt = _startAt.add(Duration(seconds: _delay)); - bool result = await widget.onChange( - TimerModel(startAt: tempStartAt,endAt: time,durationInSecond: _delay)); - if(!result) return; + bool result = await widget.onChange(TimerModel(startAt: tempStartAt, endAt: time, durationInSecond: _delay)); + if (!result) return; _running = false; _endAt = time; _startAt = tempStartAt; @@ -67,9 +66,9 @@ class _AppTimerState extends State { _onPressed() async { _loading = true; setState(() {}); - if(!_running){ + if (!_running) { await _startTimer(); - }else{ + } else { await _stopTimer(); } _loading = false; @@ -82,17 +81,19 @@ class _AppTimerState extends State { _endAt = widget.timer?.endAt; _running = _startAt != null && _endAt == null; _delay = (widget.timer?.durationInSecond ?? 0); - final difference = _startAt == null ? 0: - (_endAt ?? DateTime.now())?.difference(_startAt)?.inSeconds ?? 0; + final difference = _startAt == null ? 0 : (_endAt ?? DateTime.now())?.difference(_startAt)?.inSeconds ?? 0; _period.value = Duration(seconds: _running ? difference : _delay + difference).toString().split(".").first; super.initState(); - if(_running){_startTimer();} + if (_running) { + _startTimer(); + } } @override void dispose() { super.dispose(); } + @override Widget build(BuildContext context) { return SizedBox( @@ -100,31 +101,31 @@ class _AppTimerState extends State { height: 28 * AppStyle.getScaleFactor(context), child: ElevatedButton( style: ElevatedButton.styleFrom( - minimumSize: const Size(1, 1), - padding: EdgeInsets.all(4 * AppStyle.getScaleFactor(context)), - backgroundColor: _running ? AColors.green[300] : AColors.grey, - foregroundColor: Colors.black - ), - onPressed: _loading ? null : _onPressed, - child: _loading ? const SizedBox.square( - dimension: 18,child: CircularProgressIndicator(color: Colors.white,)): - Row( - children: [ - Icon(_running ? Icons.pause : Icons.play_arrow), - Expanded( - child: Center( - child: ValueListenableBuilder( - valueListenable: _period, - builder: (context,value,_){ - return Text(value, - style: widget.style, - ); - } - ), + minimumSize: const Size(1, 1), padding: EdgeInsets.all(4 * AppStyle.getScaleFactor(context)), backgroundColor: _running ? AColors.green[300] : AColors.grey, foregroundColor: Colors.black), + onPressed: _loading || widget.enabled == false ? null : _onPressed, + child: _loading + ? const SizedBox.square( + dimension: 18, + child: CircularProgressIndicator( + color: Colors.white, + )) + : Row( + children: [ + if (widget.enabled) Icon(_running ? Icons.pause : Icons.play_arrow), + Expanded( + child: Center( + child: ValueListenableBuilder( + valueListenable: _period, + builder: (context, value, _) { + return Text( + value, + style: widget.enabled ? widget.style : widget.style?.copyWith(color: Colors.black54), + ); + }), + ), + ), + ], ), - ), - ], - ), ), ); } diff --git a/lib/views/widgets/timer/timer_manager.dart b/lib/views/widgets/timer/timer_manager.dart index e69de29b..8b137891 100644 --- a/lib/views/widgets/timer/timer_manager.dart +++ b/lib/views/widgets/timer/timer_manager.dart @@ -0,0 +1 @@ + diff --git a/lib/views/widgets/titles/app_sub_title.dart b/lib/views/widgets/titles/app_sub_title.dart index f5651c65..4dc839cb 100644 --- a/lib/views/widgets/titles/app_sub_title.dart +++ b/lib/views/widgets/titles/app_sub_title.dart @@ -1,11 +1,14 @@ import 'package:flutter/material.dart'; import 'package:test_sa/views/app_style/sizing.dart'; + class ASubTitle extends StatelessWidget { final String text; final EdgeInsets padding; final Color color; final double font; - const ASubTitle(this.text, {Key key,this.padding, this.color, this.font}) : super(key: key); + + const ASubTitle(this.text, {Key key, this.padding, this.color, this.font}) : super(key: key); + @override Widget build(BuildContext context) { return Padding( @@ -13,10 +16,9 @@ class ASubTitle extends StatelessWidget { child: Text( text, style: Theme.of(context).textTheme.bodyText1.copyWith( - // fontWeight: FontWeight.bold, - fontSize: font, - color: color - ), + // fontWeight: FontWeight.bold, + fontSize: font, + color: color), textScaleFactor: AppStyle.getScaleFactor(context), ), ); diff --git a/lib/views/widgets/titles/app_title.dart b/lib/views/widgets/titles/app_title.dart index e97f8b9d..69020bc9 100644 --- a/lib/views/widgets/titles/app_title.dart +++ b/lib/views/widgets/titles/app_title.dart @@ -1,18 +1,19 @@ -import 'package:test_sa/views/app_style/sizing.dart'; import 'package:flutter/material.dart'; +import 'package:test_sa/views/app_style/sizing.dart'; + class ATitle extends StatelessWidget { final String text; final EdgeInsets padding; final bool center; - const ATitle(this.text, {Key key,this.padding,this.center= false}) : super(key: key); + + const ATitle(this.text, {Key key, this.padding, this.center = false}) : super(key: key); + @override Widget build(BuildContext context) { return Padding( - padding: padding ?? EdgeInsets.symmetric(horizontal: 16,vertical: 8), + padding: padding ?? EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Row( - mainAxisAlignment: center - ? MainAxisAlignment.center - : MainAxisAlignment.start, + mainAxisAlignment: center ? MainAxisAlignment.center : MainAxisAlignment.start, children: [ Text( text, diff --git a/lib/views/widgets/titles/expandable_info_row.dart b/lib/views/widgets/titles/expandable_info_row.dart index b5d24e62..369b078c 100644 --- a/lib/views/widgets/titles/expandable_info_row.dart +++ b/lib/views/widgets/titles/expandable_info_row.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:test_sa/views/app_style/sizing.dart'; + class ExpandableInfoRow extends StatefulWidget { final IconData iconData; final String title; @@ -12,13 +13,13 @@ class ExpandableInfoRow extends StatefulWidget { _ExpandableInfoRowState createState() => _ExpandableInfoRowState(); } -class _ExpandableInfoRowState extends State - with TickerProviderStateMixin{ +class _ExpandableInfoRowState extends State with TickerProviderStateMixin { bool _isExpanded = false; + @override Widget build(BuildContext context) { return InkWell( - onTap: (){ + onTap: () { _isExpanded = !_isExpanded; setState(() {}); }, @@ -26,18 +27,19 @@ class _ExpandableInfoRowState extends State children: [ Row( children: [ - widget.iconData != null ? - Padding( - padding: EdgeInsets.symmetric( - horizontal: 8 * AppStyle.getScaleFactor(context), - vertical: 2 * AppStyle.getScaleFactor(context), - ), - child: FaIcon( - widget.iconData, - color: Theme.of(context).primaryColor, - size: 20 * AppStyle.getScaleFactor(context), - ), - ):SizedBox.shrink(), + widget.iconData != null + ? Padding( + padding: EdgeInsets.symmetric( + horizontal: 8 * AppStyle.getScaleFactor(context), + vertical: 2 * AppStyle.getScaleFactor(context), + ), + child: FaIcon( + widget.iconData, + color: Theme.of(context).primaryColor, + size: 20 * AppStyle.getScaleFactor(context), + ), + ) + : SizedBox.shrink(), Expanded( flex: 2, child: Text( @@ -47,27 +49,20 @@ class _ExpandableInfoRowState extends State fontSize: 14, fontWeight: FontWeight.bold, ), - textScaleFactor: AppStyle.getScaleFactor(context), + textScaleFactor: AppStyle.getScaleFactor(context), ), ), AnimatedSwitcher( duration: Duration(milliseconds: 400), transitionBuilder: (Widget child, Animation animation) { return FadeTransition( - child: ScaleTransition( - child: child, - scale: animation - ), + child: ScaleTransition(child: child, scale: animation), opacity: animation, ); }, child: Icon( - _isExpanded - ? Icons.keyboard_arrow_up - : Icons.keyboard_arrow_down, - key: ValueKey(_isExpanded - ? "Icons.keyboard_arrow_up" - : "Icons.keyboard_arrow_down"), + _isExpanded ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down, + key: ValueKey(_isExpanded ? "Icons.keyboard_arrow_up" : "Icons.keyboard_arrow_down"), color: Theme.of(context).primaryColor, size: 24 * AppStyle.getScaleFactor(context), ), @@ -77,15 +72,18 @@ class _ExpandableInfoRowState extends State AnimatedSize( duration: Duration(milliseconds: 300), child: Visibility( - visible: _isExpanded, - child: Padding( - padding: EdgeInsets.symmetric(vertical: 8 * AppStyle.getScaleFactor(context)), - child: widget.child, - ) - ), + visible: _isExpanded, + child: Padding( + padding: EdgeInsets.symmetric(vertical: 8 * AppStyle.getScaleFactor(context)), + child: widget.child, + )), + ), + Divider( + height: 2 * AppStyle.getScaleFactor(context), + ), + SizedBox( + height: 8 * AppStyle.getScaleFactor(context), ), - Divider(height: 2 * AppStyle.getScaleFactor(context),), - SizedBox(height: 8 * AppStyle.getScaleFactor(context),), ], ), ); diff --git a/lib/views/widgets/visits/visit_item.dart b/lib/views/widgets/visits/visit_item.dart index bd456d19..fc8e2052 100644 --- a/lib/views/widgets/visits/visit_item.dart +++ b/lib/views/widgets/visits/visit_item.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/localization/localization.dart'; @@ -22,27 +21,28 @@ class VisitItem extends StatelessWidget { @override Widget build(BuildContext context) { - UserProvider _userProvider = Provider.of(context); + UserProvider userProvider = Provider.of(context); Color itemColor = index % 2 == 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; Color onItemColor = index % 2 != 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onPrimary; - Subtitle _subtitle = AppLocalization.of(context).subtitle; + Subtitle subtitle = AppLocalization.of(context).subtitle; return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: ElevatedButton( style: ElevatedButton.styleFrom( - padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8), - primary: itemColor, + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 8), + backgroundColor: itemColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), ), ), onPressed: () { - if (activeSelectMod && _userProvider.user.type == UsersTypes.engineer) + if (activeSelectMod && userProvider.user.type == UsersTypes.engineer) { onSelect(visit); - else + } else { onPressed(visit); + } }, - onLongPress: _userProvider.user.type == UsersTypes.engineer + onLongPress: userProvider.user.type == UsersTypes.engineer ? () { onLongPress(visit); } @@ -54,12 +54,12 @@ class VisitItem extends StatelessWidget { children: [ Expanded( child: Text( - "S.N: " + visit.deviceSerialNumber ?? "No serial number", - style: Theme.of(context).textTheme.headline6.copyWith(color: onItemColor, fontSize: 16, fontWeight: FontWeight.bold), + "S.N: ${visit.deviceSerialNumber}" ?? "No serial number", + style: Theme.of(context).textTheme.titleLarge.copyWith(color: onItemColor, fontSize: 16, fontWeight: FontWeight.bold), ), ), AnimatedSwitcher( - duration: Duration(milliseconds: 400), + duration: const Duration(milliseconds: 400), child: Visibility( key: ValueKey(activeSelectMod), visible: activeSelectMod, @@ -82,12 +82,19 @@ class VisitItem extends StatelessWidget { Divider( color: onItemColor, ), + Text( + visit.deviceNumber ?? "", + style: Theme.of(context).textTheme.titleMedium.copyWith(color: onItemColor, fontSize: 14), + ), + Divider( + color: onItemColor, + ), Row( children: [ Expanded( child: Text( visit.hospitalName ?? "No client found", - style: Theme.of(context).textTheme.subtitle1.copyWith( + style: Theme.of(context).textTheme.titleMedium.copyWith( color: onItemColor, fontSize: 14, ), @@ -97,31 +104,30 @@ class VisitItem extends StatelessWidget { ), Text( visit.modelAndBrand ?? "", - style: Theme.of(context).textTheme.subtitle1.copyWith( + style: Theme.of(context).textTheme.titleMedium.copyWith( color: onItemColor, fontSize: 14, ), ), - Divider( - color: onItemColor, - ), - Row( - children: [ - Expanded( - child: Text( - visit.employName ?? "No employ found", - style: Theme.of(context).textTheme.headline6.copyWith(color: onItemColor, fontSize: 14, fontWeight: FontWeight.bold), + if (visit.employName != null && visit.employName.isNotEmpty) Divider(color: onItemColor), + if (visit.employName != null && visit.employName.isNotEmpty) + Row( + children: [ + Expanded( + child: Text( + visit.employName ?? "No employ found", + style: Theme.of(context).textTheme.titleLarge.copyWith(color: onItemColor, fontSize: 14, fontWeight: FontWeight.bold), + ), ), - ), - Text( - visit.contactStatus ?? "", - style: Theme.of(context).textTheme.subtitle1.copyWith( - color: onItemColor, - fontSize: 14, - ), - ), - ], - ), + // Text( + // visit.contactStatus ?? "", + // style: Theme.of(context).textTheme.subtitle1.copyWith( + // color: onItemColor, + // fontSize: 14, + // ), + // ), + ], + ), Divider( color: onItemColor, ), @@ -132,18 +138,12 @@ class VisitItem extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - _subtitle.expectDate, - style: Theme.of(context).textTheme.headline6.copyWith( - color: onItemColor, - fontSize: 14, - ), + subtitle.expectDate, + style: Theme.of(context).textTheme.titleLarge.copyWith(color: onItemColor, fontSize: 14), ), Text( - visit.expectDate ?? _subtitle.noDateFound, - style: Theme.of(context).textTheme.headline6.copyWith( - color: onItemColor, - fontSize: 14, - ), + visit.expectDate ?? subtitle.noDateFound, + style: Theme.of(context).textTheme.titleLarge.copyWith(color: onItemColor, fontSize: 14), ), ], ), @@ -152,18 +152,12 @@ class VisitItem extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - _subtitle.actualDate, - style: Theme.of(context).textTheme.headline6.copyWith( - color: onItemColor, - fontSize: 14, - ), + subtitle.actualDate, + style: Theme.of(context).textTheme.titleLarge.copyWith(color: onItemColor, fontSize: 14), ), Text( - visit.actualDate ?? _subtitle.noDateFound, - style: Theme.of(context).textTheme.headline6.copyWith( - color: onItemColor, - fontSize: 14, - ), + visit.actualDate ?? subtitle.noDateFound, + style: Theme.of(context).textTheme.titleLarge.copyWith(color: onItemColor, fontSize: 14), ), ], ), diff --git a/lib/views/widgets/visits/visit_status.dart b/lib/views/widgets/visits/visit_status.dart index 871287fe..f582fe95 100644 --- a/lib/views/widgets/visits/visit_status.dart +++ b/lib/views/widgets/visits/visit_status.dart @@ -2,43 +2,36 @@ import 'package:flutter/material.dart'; import 'package:test_sa/models/visits/visit.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; + class VisitStatusLabel extends StatelessWidget { final Visit visit; const VisitStatusLabel({Key key, this.visit}) : super(key: key); - Color getStatusColor(){ - switch(visit.status.id){ - case 0: return AColors.green; - case 1: return AColors.grey; - case 2: return AColors.grey; - default : return AColors.grey; + Color getStatusColor() { + switch (visit.status.id) { + case 0: + return AColors.green; + case 1: + return AColors.grey; + case 2: + return AColors.grey; + default: + return AColors.grey; } } @override Widget build(BuildContext context) { - return Container( - padding: EdgeInsets.symmetric(vertical: 2,horizontal: 8), + return Container( + padding: EdgeInsets.symmetric(vertical: 2, horizontal: 8), alignment: Alignment.center, - decoration: BoxDecoration( - color: getStatusColor(), - borderRadius: BorderRadius.circular( - AppStyle.getBorderRadius(context) - ), - boxShadow: [ - AppStyle.boxShadow - ] - ), + decoration: BoxDecoration(color: getStatusColor(), borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [AppStyle.boxShadow]), child: Text( - visit.status.label == null - || visit.status.label.isEmpty - ? "no status" :visit.status.label, + visit.status.name == null || visit.status.name.isEmpty ? "no status" : visit.status.name, style: Theme.of(context).textTheme.subtitle2.copyWith( - color: getStatusColor().computeLuminance() > 0.5 - ? AColors.black : Colors.white, - ), - ) - ); + color: getStatusColor().computeLuminance() > 0.5 ? AColors.black : Colors.white, + ), + )); } } diff --git a/lib/views/widgets/visits/visits_list.dart b/lib/views/widgets/visits/visits_list.dart index a5b05966..bb327679 100644 --- a/lib/views/widgets/visits/visits_list.dart +++ b/lib/views/widgets/visits/visits_list.dart @@ -1,3 +1,4 @@ +import 'package:flutter/material.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/models/visits/visit.dart'; @@ -6,37 +7,35 @@ import 'package:test_sa/views/pages/user/visits/visit_details.dart'; import 'package:test_sa/views/widgets/loaders/lazy_loading.dart'; import 'package:test_sa/views/widgets/loaders/no_item_found.dart'; import 'package:test_sa/views/widgets/visits/visit_item.dart'; -import 'package:flutter/material.dart'; + class VisitsList extends StatefulWidget { final List visits; final bool nextPage; final Future Function() onLazyLoad; final Function(List) onEditGroup; - const VisitsList({ - Key key, - this.visits, - this.nextPage, - this.onLazyLoad, - this.onEditGroup - }) : super(key: key); + const VisitsList({Key key, this.visits, this.nextPage, this.onLazyLoad, this.onEditGroup}) : super(key: key); @override _VisitsListState createState() => _VisitsListState(); } class _VisitsListState extends State { - List _selectedVisits = []; + final List _selectedVisits = []; + @override void initState() { _selectedVisits.clear(); super.initState(); } + @override Widget build(BuildContext context) { - Subtitle _subtitle = AppLocalization.of(context).subtitle; - if(widget.visits.length == 0){ - return NoItemFound(message: _subtitle.noVisitsFound,); + Subtitle subtitle = AppLocalization.of(context).subtitle; + if (widget.visits.isEmpty) { + return NoItemFound( + message: subtitle.noVisitsFound, + ); } return Stack( children: [ @@ -44,34 +43,33 @@ class _VisitsListState extends State { nextPage: widget.nextPage, onLazyLoad: widget.onLazyLoad, child: ListView.builder( - //physics: BouncingScrollPhysics(), - itemCount: widget.visits.length, - padding: EdgeInsets.symmetric(horizontal: 16,vertical: 8), - itemBuilder: (context,itemIndex){ - Visit _visit = widget.visits[itemIndex]; - bool _isSelected = _selectedVisits.contains(_visit); + //physics: BouncingScrollPhysics(), + itemCount: widget.visits.length, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + itemBuilder: (context, itemIndex) { + Visit visit = widget.visits[itemIndex]; + bool isSelected = _selectedVisits.contains(visit); return VisitItem( - visit: _visit, - isSelected: _isSelected, + visit: visit, + isSelected: isSelected, index: itemIndex, activeSelectMod: _selectedVisits.isNotEmpty, - onPressed: (visit){ - Navigator.of(context).push( - MaterialPageRoute( - builder: (_)=> VisitDetailsPage(visit: visit,) - ) - ); + onPressed: (visit) { + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => VisitDetailsPage( + visit: visit, + ))); }, - onSelect: (visit){ - if(_isSelected){ + onSelect: (visit) { + if (isSelected) { _selectedVisits.remove(visit); } else { _selectedVisits.add(visit); } setState(() {}); }, - onLongPress: (visit){ - if(_isSelected){ + onLongPress: (visit) { + if (isSelected) { _selectedVisits.remove(visit); } else { _selectedVisits.add(visit); @@ -79,15 +77,14 @@ class _VisitsListState extends State { setState(() {}); }, ); - } - ), + }), ), Align( alignment: Alignment.bottomLeft, child: Padding( padding: EdgeInsets.all(8.0 * AppStyle.getScaleFactor(context)), child: AnimatedSwitcher( - duration: Duration(milliseconds: 400), + duration: const Duration(milliseconds: 400), child: Visibility( key: ValueKey(_selectedVisits.isNotEmpty), visible: _selectedVisits.isNotEmpty, @@ -96,17 +93,17 @@ class _VisitsListState extends State { children: [ FloatingActionButton( heroTag: "cancel", - child: Icon(Icons.cancel), - onPressed: (){ + child: const Icon(Icons.cancel), + onPressed: () { _selectedVisits.clear(); setState(() {}); }, ), FloatingActionButton( heroTag: "edit", - child: Icon(Icons.edit), - onPressed: (){ - if(!widget.visits.contains(_selectedVisits.first)){ + child: const Icon(Icons.edit), + onPressed: () { + if (!widget.visits.contains(_selectedVisits.first)) { _selectedVisits.clear(); setState(() {}); return; diff --git a/pubspec.lock b/pubspec.lock deleted file mode 100644 index 8608b33d..00000000 --- a/pubspec.lock +++ /dev/null @@ -1,1025 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _flutterfire_internals: - dependency: transitive - description: - name: _flutterfire_internals - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.12" - archive: - dependency: transitive - description: - name: archive - url: "https://pub.dartlang.org" - source: hosted - version: "3.3.5" - args: - dependency: transitive - description: - name: args - url: "https://pub.dartlang.org" - source: hosted - version: "2.3.1" - async: - dependency: transitive - description: - name: async - url: "https://pub.dartlang.org" - source: hosted - version: "2.9.0" - audioplayers: - dependency: "direct main" - description: - name: audioplayers - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - audioplayers_android: - dependency: transitive - description: - name: audioplayers_android - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.3" - audioplayers_darwin: - dependency: transitive - description: - name: audioplayers_darwin - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.4" - audioplayers_linux: - dependency: transitive - description: - name: audioplayers_linux - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" - audioplayers_platform_interface: - dependency: transitive - description: - name: audioplayers_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - audioplayers_web: - dependency: transitive - description: - name: audioplayers_web - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - audioplayers_windows: - dependency: transitive - description: - name: audioplayers_windows - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.1" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - cached_network_image: - dependency: "direct main" - description: - name: cached_network_image - url: "https://pub.dartlang.org" - source: hosted - version: "3.2.3" - cached_network_image_platform_interface: - dependency: transitive - description: - name: cached_network_image_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - cached_network_image_web: - dependency: transitive - description: - name: cached_network_image_web - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" - carousel_slider: - dependency: "direct main" - description: - name: carousel_slider - url: "https://pub.dartlang.org" - source: hosted - version: "4.2.1" - characters: - dependency: transitive - description: - name: characters - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.1" - checked_yaml: - dependency: transitive - description: - name: checked_yaml - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.2" - cli_util: - dependency: transitive - description: - name: cli_util - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.5" - clock: - dependency: transitive - description: - name: clock - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.1" - collection: - dependency: transitive - description: - name: collection - url: "https://pub.dartlang.org" - source: hosted - version: "1.16.0" - convert: - dependency: transitive - description: - name: convert - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.1" - cross_file: - dependency: transitive - description: - name: cross_file - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.3+2" - crypto: - dependency: transitive - description: - name: crypto - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.2" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.5" - dbus: - dependency: transitive - description: - name: dbus - url: "https://pub.dartlang.org" - source: hosted - version: "0.7.8" - fake_async: - dependency: transitive - description: - name: fake_async - url: "https://pub.dartlang.org" - source: hosted - 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" - firebase_core: - dependency: "direct main" - description: - name: firebase_core - url: "https://pub.dartlang.org" - source: hosted - version: "2.4.1" - firebase_core_platform_interface: - dependency: transitive - description: - name: firebase_core_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "4.5.2" - firebase_core_web: - dependency: transitive - description: - name: firebase_core_web - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - firebase_messaging: - dependency: "direct main" - description: - name: firebase_messaging - url: "https://pub.dartlang.org" - source: hosted - version: "14.2.1" - firebase_messaging_platform_interface: - dependency: transitive - description: - name: firebase_messaging_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "4.2.10" - firebase_messaging_web: - dependency: transitive - description: - name: firebase_messaging_web - url: "https://pub.dartlang.org" - source: hosted - version: "3.2.11" - flare_flutter: - dependency: "direct main" - description: - name: flare_flutter - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.2" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_blurhash: - dependency: transitive - description: - name: flutter_blurhash - url: "https://pub.dartlang.org" - source: hosted - version: "0.7.0" - flutter_cache_manager: - dependency: transitive - description: - name: flutter_cache_manager - url: "https://pub.dartlang.org" - source: hosted - version: "3.3.0" - flutter_keyboard_visibility: - dependency: transitive - description: - name: flutter_keyboard_visibility - url: "https://pub.dartlang.org" - source: hosted - version: "5.4.0" - flutter_keyboard_visibility_linux: - dependency: transitive - description: - name: flutter_keyboard_visibility_linux - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - flutter_keyboard_visibility_macos: - dependency: transitive - description: - name: flutter_keyboard_visibility_macos - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - flutter_keyboard_visibility_platform_interface: - dependency: transitive - description: - name: flutter_keyboard_visibility_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - flutter_keyboard_visibility_web: - dependency: transitive - description: - name: flutter_keyboard_visibility_web - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - flutter_keyboard_visibility_windows: - dependency: transitive - description: - name: flutter_keyboard_visibility_windows - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - flutter_launcher_icons: - dependency: "direct main" - description: - name: flutter_launcher_icons - url: "https://pub.dartlang.org" - source: hosted - version: "0.10.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - flutter_local_notifications: - dependency: "direct main" - description: - name: flutter_local_notifications - url: "https://pub.dartlang.org" - source: hosted - version: "12.0.4" - flutter_local_notifications_linux: - dependency: transitive - description: - name: flutter_local_notifications_linux - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - flutter_local_notifications_platform_interface: - dependency: transitive - description: - name: flutter_local_notifications_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "6.0.0" - flutter_localizations: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_plugin_android_lifecycle: - dependency: transitive - description: - name: flutter_plugin_android_lifecycle - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.7" - flutter_sound: - dependency: "direct main" - description: - name: flutter_sound - url: "https://pub.dartlang.org" - source: hosted - version: "9.2.13" - flutter_sound_platform_interface: - dependency: transitive - description: - name: flutter_sound_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "9.2.13" - flutter_sound_web: - dependency: transitive - description: - name: flutter_sound_web - url: "https://pub.dartlang.org" - source: hosted - version: "9.2.13" - flutter_svg: - dependency: transitive - description: - name: flutter_svg - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.6" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_typeahead: - dependency: "direct main" - description: - name: flutter_typeahead - url: "https://pub.dartlang.org" - source: hosted - version: "4.1.1" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - fluttertoast: - dependency: "direct main" - description: - name: fluttertoast - url: "https://pub.dartlang.org" - source: hosted - version: "8.1.2" - font_awesome_flutter: - dependency: "direct main" - description: - name: font_awesome_flutter - url: "https://pub.dartlang.org" - source: hosted - version: "10.3.0" - graphs: - dependency: transitive - description: - name: graphs - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.0" - http: - dependency: "direct main" - description: - name: http - url: "https://pub.dartlang.org" - source: hosted - version: "0.13.5" - http_parser: - dependency: transitive - description: - name: http_parser - url: "https://pub.dartlang.org" - source: hosted - version: "4.0.2" - image: - dependency: transitive - description: - name: image - url: "https://pub.dartlang.org" - source: hosted - version: "3.3.0" - image_picker: - dependency: "direct main" - description: - name: image_picker - url: "https://pub.dartlang.org" - source: hosted - version: "0.8.6" - image_picker_android: - dependency: transitive - description: - name: image_picker_android - url: "https://pub.dartlang.org" - source: hosted - version: "0.8.5+4" - image_picker_for_web: - dependency: transitive - description: - name: image_picker_for_web - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.10" - image_picker_ios: - dependency: transitive - description: - name: image_picker_ios - url: "https://pub.dartlang.org" - source: hosted - version: "0.8.6+5" - image_picker_platform_interface: - dependency: transitive - description: - name: image_picker_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.6.2" - intl: - dependency: "direct main" - description: - name: intl - url: "https://pub.dartlang.org" - source: hosted - version: "0.17.0" - js: - dependency: transitive - description: - name: js - url: "https://pub.dartlang.org" - source: hosted - version: "0.6.4" - json_annotation: - dependency: transitive - description: - name: json_annotation - url: "https://pub.dartlang.org" - source: hosted - version: "4.7.0" - lints: - dependency: transitive - description: - name: lints - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - logger: - dependency: transitive - description: - name: logger - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - matcher: - dependency: transitive - description: - name: matcher - url: "https://pub.dartlang.org" - source: hosted - 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.8.0" - mime: - dependency: transitive - description: - name: mime - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.3" - nested: - dependency: transitive - description: - name: nested - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - octo_image: - dependency: transitive - description: - name: octo_image - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" - package_info: - dependency: "direct main" - description: - name: package_info - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.2" - path: - dependency: transitive - description: - name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.2" - path_drawing: - dependency: transitive - description: - name: path_drawing - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - path_parsing: - dependency: transitive - description: - name: path_parsing - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - 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.22" - 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" - pedantic: - dependency: transitive - description: - name: pedantic - url: "https://pub.dartlang.org" - source: hosted - version: "1.11.1" - permission_handler: - dependency: "direct main" - description: - name: permission_handler - url: "https://pub.dartlang.org" - source: hosted - version: "10.2.0" - permission_handler_android: - dependency: transitive - description: - name: permission_handler_android - url: "https://pub.dartlang.org" - source: hosted - version: "10.2.0" - permission_handler_apple: - dependency: transitive - description: - name: permission_handler_apple - url: "https://pub.dartlang.org" - source: hosted - version: "9.0.7" - permission_handler_platform_interface: - dependency: transitive - description: - name: permission_handler_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "3.9.0" - permission_handler_windows: - dependency: transitive - description: - name: permission_handler_windows - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.2" - petitparser: - dependency: transitive - description: - name: petitparser - url: "https://pub.dartlang.org" - source: hosted - version: "5.1.0" - platform: - dependency: transitive - description: - name: platform - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.0" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.3" - pointycastle: - dependency: transitive - description: - name: pointycastle - url: "https://pub.dartlang.org" - source: hosted - version: "3.6.2" - process: - dependency: transitive - description: - name: process - url: "https://pub.dartlang.org" - source: hosted - version: "4.2.4" - provider: - dependency: "direct main" - description: - name: provider - url: "https://pub.dartlang.org" - source: hosted - version: "6.0.5" - qr_code_scanner: - dependency: "direct main" - description: - name: qr_code_scanner - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - recase: - dependency: transitive - description: - name: recase - url: "https://pub.dartlang.org" - source: hosted - version: "4.1.0" - rive: - dependency: "direct main" - description: - name: rive - url: "https://pub.dartlang.org" - source: hosted - version: "0.9.1" - rxdart: - dependency: transitive - description: - name: rxdart - url: "https://pub.dartlang.org" - source: hosted - version: "0.27.7" - share: - dependency: "direct main" - description: - name: share - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.4" - shared_preferences: - dependency: "direct main" - description: - name: shared_preferences - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.15" - shared_preferences_android: - dependency: transitive - description: - name: shared_preferences_android - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.14" - shared_preferences_ios: - dependency: transitive - description: - name: shared_preferences_ios - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.1" - shared_preferences_linux: - dependency: transitive - description: - name: shared_preferences_linux - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.2" - shared_preferences_macos: - dependency: transitive - description: - name: shared_preferences_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.5" - shared_preferences_platform_interface: - dependency: transitive - description: - name: shared_preferences_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - shared_preferences_web: - dependency: transitive - description: - name: shared_preferences_web - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.4" - shared_preferences_windows: - dependency: transitive - description: - name: shared_preferences_windows - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.2" - signature: - dependency: "direct main" - description: - name: signature - url: "https://pub.dartlang.org" - source: hosted - version: "5.3.0" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_span: - dependency: transitive - description: - name: source_span - url: "https://pub.dartlang.org" - source: hosted - version: "1.9.0" - speech_to_text: - dependency: "direct main" - description: - name: speech_to_text - url: "https://pub.dartlang.org" - source: hosted - version: "6.1.1" - speech_to_text_macos: - dependency: transitive - description: - name: speech_to_text_macos - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" - speech_to_text_platform_interface: - dependency: transitive - description: - name: speech_to_text_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - sqflite: - dependency: transitive - description: - name: sqflite - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.2" - sqflite_common: - dependency: transitive - description: - name: sqflite_common - url: "https://pub.dartlang.org" - source: hosted - version: "2.4.0+2" - stack_trace: - dependency: transitive - description: - name: stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.10.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - string_scanner: - dependency: transitive - description: - name: string_scanner - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.1" - synchronized: - dependency: transitive - description: - name: synchronized - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.0+3" - term_glyph: - dependency: transitive - description: - name: term_glyph - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.1" - test_api: - dependency: transitive - description: - name: test_api - url: "https://pub.dartlang.org" - source: hosted - version: "0.4.12" - timezone: - dependency: transitive - description: - name: timezone - url: "https://pub.dartlang.org" - source: hosted - version: "0.9.1" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" - url_launcher: - dependency: "direct main" - description: - name: url_launcher - url: "https://pub.dartlang.org" - source: hosted - version: "6.1.7" - url_launcher_android: - dependency: transitive - description: - name: url_launcher_android - url: "https://pub.dartlang.org" - source: hosted - version: "6.0.22" - url_launcher_ios: - dependency: transitive - description: - name: url_launcher_ios - url: "https://pub.dartlang.org" - source: hosted - version: "6.0.17" - url_launcher_linux: - dependency: transitive - description: - name: url_launcher_linux - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.1" - url_launcher_macos: - dependency: transitive - description: - name: url_launcher_macos - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.1" - url_launcher_platform_interface: - dependency: transitive - description: - name: url_launcher_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.1" - url_launcher_web: - dependency: transitive - description: - name: url_launcher_web - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.13" - url_launcher_windows: - dependency: transitive - description: - name: url_launcher_windows - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.1" - uuid: - dependency: transitive - description: - name: uuid - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.7" - vector_math: - dependency: transitive - description: - name: vector_math - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.2" - win32: - dependency: transitive - description: - name: win32 - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.3" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.0+2" - xml: - dependency: transitive - description: - name: xml - url: "https://pub.dartlang.org" - source: hosted - version: "6.1.0" - yaml: - dependency: transitive - description: - name: yaml - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.1" -sdks: - dart: ">=2.18.0 <3.0.0" - flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index 99885208..076379b6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -60,7 +60,8 @@ dependencies: audioplayers: ^1.1.1 flare_flutter: ^3.0.2 signature: ^5.3.0 - + flutter_svg: ^1.1.6 + file_picker: ^5.2.5 dev_dependencies: flutter_test: