diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 00000000..ffbf5eb6 --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,371 @@ +PODS: + - audio_session (0.0.1): + - Flutter + - audioplayers_darwin (0.0.1): + - Flutter + - device_calendar (0.0.1): + - Flutter + - DKImagePickerController/Core (4.3.9): + - DKImagePickerController/ImageDataManager + - DKImagePickerController/Resource + - DKImagePickerController/ImageDataManager (4.3.9) + - DKImagePickerController/PhotoGallery (4.3.9): + - DKImagePickerController/Core + - DKPhotoGallery + - DKImagePickerController/Resource (4.3.9) + - DKPhotoGallery (0.0.19): + - DKPhotoGallery/Core (= 0.0.19) + - DKPhotoGallery/Model (= 0.0.19) + - DKPhotoGallery/Preview (= 0.0.19) + - DKPhotoGallery/Resource (= 0.0.19) + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Core (0.0.19): + - DKPhotoGallery/Model + - DKPhotoGallery/Preview + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Model (0.0.19): + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Preview (0.0.19): + - DKPhotoGallery/Model + - DKPhotoGallery/Resource + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Resource (0.0.19): + - SDWebImage + - SwiftyGif + - DTTJailbreakDetection (0.4.0) + - file_picker (0.0.1): + - DKImagePickerController/PhotoGallery + - Flutter + - Firebase/CoreOnly (11.2.0): + - FirebaseCore (= 11.2.0) + - Firebase/Messaging (11.2.0): + - Firebase/CoreOnly + - FirebaseMessaging (~> 11.2.0) + - firebase_core (3.6.0): + - Firebase/CoreOnly (= 11.2.0) + - Flutter + - firebase_messaging (15.1.3): + - Firebase/Messaging (= 11.2.0) + - firebase_core + - Flutter + - FirebaseCore (11.2.0): + - FirebaseCoreInternal (~> 11.0) + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/Logger (~> 8.0) + - FirebaseCoreInternal (11.9.0): + - "GoogleUtilities/NSData+zlib (~> 8.0)" + - FirebaseInstallations (11.4.0): + - FirebaseCore (~> 11.0) + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/UserDefaults (~> 8.0) + - PromisesObjC (~> 2.4) + - FirebaseMessaging (11.2.0): + - FirebaseCore (~> 11.0) + - FirebaseInstallations (~> 11.0) + - GoogleDataTransport (~> 10.0) + - GoogleUtilities/AppDelegateSwizzler (~> 8.0) + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/Reachability (~> 8.0) + - GoogleUtilities/UserDefaults (~> 8.0) + - nanopb (~> 3.30910.0) + - Flutter (1.0.0) + - flutter_keyboard_visibility (0.0.1): + - Flutter + - flutter_local_notifications (0.0.1): + - Flutter + - flutter_sound (9.6.0): + - Flutter + - flutter_sound_core (= 9.6.0) + - flutter_sound_core (9.6.0) + - flutter_timezone (0.0.1): + - Flutter + - fluttertoast (0.0.2): + - Flutter + - Toast + - FMDB (2.7.12): + - FMDB/standard (= 2.7.12) + - FMDB/Core (2.7.12) + - FMDB/standard (2.7.12): + - FMDB/Core + - geolocator_apple (1.2.0): + - Flutter + - GoogleDataTransport (10.1.0): + - nanopb (~> 3.30910.0) + - PromisesObjC (~> 2.4) + - GoogleUtilities/AppDelegateSwizzler (8.0.2): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Privacy + - GoogleUtilities/Environment (8.0.2): + - GoogleUtilities/Privacy + - GoogleUtilities/Logger (8.0.2): + - GoogleUtilities/Environment + - GoogleUtilities/Privacy + - GoogleUtilities/Network (8.0.2): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Privacy + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (8.0.2)": + - GoogleUtilities/Privacy + - GoogleUtilities/Privacy (8.0.2) + - GoogleUtilities/Reachability (8.0.2): + - GoogleUtilities/Logger + - GoogleUtilities/Privacy + - GoogleUtilities/UserDefaults (8.0.2): + - GoogleUtilities/Logger + - GoogleUtilities/Privacy + - image_cropper (0.0.4): + - Flutter + - TOCropViewController (~> 2.7.4) + - image_picker_ios (0.0.1): + - Flutter + - just_audio (0.0.1): + - Flutter + - local_auth_darwin (0.0.1): + - Flutter + - FlutterMacOS + - MTBBarcodeScanner (5.0.11) + - nanopb (3.30910.0): + - nanopb/decode (= 3.30910.0) + - nanopb/encode (= 3.30910.0) + - nanopb/decode (3.30910.0) + - nanopb/encode (3.30910.0) + - nfc_manager (0.0.1): + - Flutter + - open_file_ios (0.0.1): + - Flutter + - package_info_plus (0.4.5): + - Flutter + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - permission_handler_apple (9.3.0): + - Flutter + - pointer_interceptor_ios (0.0.1): + - Flutter + - PromisesObjC (2.4.0) + - qr_code_scanner (0.2.0): + - Flutter + - MTBBarcodeScanner + - record_mp3_plus (1.0.0): + - Flutter + - rive_common (0.0.1): + - Flutter + - safe_device (1.0.0): + - DTTJailbreakDetection + - Flutter + - SDWebImage (5.21.0): + - SDWebImage/Core (= 5.21.0) + - SDWebImage/Core (5.21.0) + - share_plus (0.0.1): + - Flutter + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + - speech_to_text (0.0.1): + - Flutter + - FlutterMacOS + - Try + - sqflite (0.0.3): + - Flutter + - FlutterMacOS + - SwiftyGif (5.4.5) + - Toast (4.1.1) + - TOCropViewController (2.7.4) + - Try (2.1.1) + - url_launcher_ios (0.0.1): + - Flutter + - wifi_iot (0.0.1): + - Flutter + +DEPENDENCIES: + - audio_session (from `.symlinks/plugins/audio_session/ios`) + - audioplayers_darwin (from `.symlinks/plugins/audioplayers_darwin/ios`) + - device_calendar (from `.symlinks/plugins/device_calendar/ios`) + - file_picker (from `.symlinks/plugins/file_picker/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`) + - flutter_timezone (from `.symlinks/plugins/flutter_timezone/ios`) + - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) + - FMDB + - geolocator_apple (from `.symlinks/plugins/geolocator_apple/ios`) + - image_cropper (from `.symlinks/plugins/image_cropper/ios`) + - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) + - just_audio (from `.symlinks/plugins/just_audio/ios`) + - local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`) + - nfc_manager (from `.symlinks/plugins/nfc_manager/ios`) + - open_file_ios (from `.symlinks/plugins/open_file_ios/ios`) + - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) + - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) + - pointer_interceptor_ios (from `.symlinks/plugins/pointer_interceptor_ios/ios`) + - qr_code_scanner (from `.symlinks/plugins/qr_code_scanner/ios`) + - record_mp3_plus (from `.symlinks/plugins/record_mp3_plus/ios`) + - rive_common (from `.symlinks/plugins/rive_common/ios`) + - safe_device (from `.symlinks/plugins/safe_device/ios`) + - share_plus (from `.symlinks/plugins/share_plus/ios`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) + - speech_to_text (from `.symlinks/plugins/speech_to_text/darwin`) + - sqflite (from `.symlinks/plugins/sqflite/darwin`) + - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) + - wifi_iot (from `.symlinks/plugins/wifi_iot/ios`) + +SPEC REPOS: + trunk: + - DKImagePickerController + - DKPhotoGallery + - DTTJailbreakDetection + - Firebase + - FirebaseCore + - FirebaseCoreInternal + - FirebaseInstallations + - FirebaseMessaging + - flutter_sound_core + - FMDB + - GoogleDataTransport + - GoogleUtilities + - MTBBarcodeScanner + - nanopb + - PromisesObjC + - SDWebImage + - SwiftyGif + - Toast + - TOCropViewController + - Try + +EXTERNAL SOURCES: + audio_session: + :path: ".symlinks/plugins/audio_session/ios" + audioplayers_darwin: + :path: ".symlinks/plugins/audioplayers_darwin/ios" + device_calendar: + :path: ".symlinks/plugins/device_calendar/ios" + file_picker: + :path: ".symlinks/plugins/file_picker/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" + flutter_timezone: + :path: ".symlinks/plugins/flutter_timezone/ios" + fluttertoast: + :path: ".symlinks/plugins/fluttertoast/ios" + geolocator_apple: + :path: ".symlinks/plugins/geolocator_apple/ios" + image_cropper: + :path: ".symlinks/plugins/image_cropper/ios" + image_picker_ios: + :path: ".symlinks/plugins/image_picker_ios/ios" + just_audio: + :path: ".symlinks/plugins/just_audio/ios" + local_auth_darwin: + :path: ".symlinks/plugins/local_auth_darwin/darwin" + nfc_manager: + :path: ".symlinks/plugins/nfc_manager/ios" + open_file_ios: + :path: ".symlinks/plugins/open_file_ios/ios" + package_info_plus: + :path: ".symlinks/plugins/package_info_plus/ios" + path_provider_foundation: + :path: ".symlinks/plugins/path_provider_foundation/darwin" + permission_handler_apple: + :path: ".symlinks/plugins/permission_handler_apple/ios" + pointer_interceptor_ios: + :path: ".symlinks/plugins/pointer_interceptor_ios/ios" + qr_code_scanner: + :path: ".symlinks/plugins/qr_code_scanner/ios" + record_mp3_plus: + :path: ".symlinks/plugins/record_mp3_plus/ios" + rive_common: + :path: ".symlinks/plugins/rive_common/ios" + safe_device: + :path: ".symlinks/plugins/safe_device/ios" + share_plus: + :path: ".symlinks/plugins/share_plus/ios" + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/darwin" + speech_to_text: + :path: ".symlinks/plugins/speech_to_text/darwin" + sqflite: + :path: ".symlinks/plugins/sqflite/darwin" + url_launcher_ios: + :path: ".symlinks/plugins/url_launcher_ios/ios" + wifi_iot: + :path: ".symlinks/plugins/wifi_iot/ios" + +SPEC CHECKSUMS: + audio_session: 088d2483ebd1dc43f51d253d4a1c517d9a2e7207 + audioplayers_darwin: 877d9a4d06331c5c374595e46e16453ac7eafa40 + device_calendar: 9cb33f88a02e19652ec7b8b122ca778f751b1f7b + DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c + DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 + DTTJailbreakDetection: 5e356c5badc17995f65a83ed9483f787a0057b71 + file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655 + Firebase: 98e6bf5278170668a7983e12971a66b2cd57fc8c + firebase_core: 2bedc3136ec7c7b8561c6123ed0239387b53f2af + firebase_messaging: 15d114e1a41fc31e4fbabcd48d765a19eec94a38 + FirebaseCore: a282032ae9295c795714ded2ec9c522fc237f8da + FirebaseCoreInternal: 154779013b85b4b290fdba38414df475f42e3096 + FirebaseInstallations: 6ef4a1c7eb2a61ee1f74727d7f6ce2e72acf1414 + FirebaseMessaging: c9ec7b90c399c7a6100297e9d16f8a27fc7f7152 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069 + flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086 + flutter_sound: dde9a913063b65a27ba8fdc2039036b99b136c79 + flutter_sound_core: 0c6eb9d5268adc70ff159b3d65fd3d98a82d3a27 + flutter_timezone: ffb07bdad3c6276af8dada0f11978d8a1f8a20bb + fluttertoast: 723e187574b149e68e63ca4d39b837586b903cfa + FMDB: 728731dd336af3936ce00f91d9d8495f5718a0e6 + geolocator_apple: 9bcea1918ff7f0062d98345d238ae12718acfbc1 + GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 + GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d + image_cropper: 37d40f62177c101ff4c164906d259ea2c3aa70cf + image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 + just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa + local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3 + MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb + nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 + nfc_manager: d7da7cb781f7744b94df5fe9dbca904ac4a0939e + open_file_ios: 461db5853723763573e140de3193656f91990d9e + package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 + permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 + pointer_interceptor_ios: 508241697ff0947f853c061945a8b822463947c1 + PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 + qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e + record_mp3_plus: be7806da5b5ff9694f8069f401120853c89f3398 + rive_common: cbbac3192af00d7341f19dae2f26298e9e37d99e + safe_device: 4539eb6bdbeb4b61a763a51c4e73e6b37dea4e3d + SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868 + share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + speech_to_text: 627d3fd2194770b51abb324ba45c2d39398f24a8 + sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec + SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 + Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e + TOCropViewController: 80b8985ad794298fb69d3341de183f33d1853654 + Try: 5ef669ae832617b3cee58cb2c6f99fb767a4ff96 + url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe + wifi_iot: b5aafd6f9b52f8a357383a1deabab45f31cd602d + +PODFILE CHECKSUM: d8654c27146ad2b7c852fbdd93ef1a3785d9310b + +COCOAPODS: 1.12.0 diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 9857c9a5..33d25350 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -2,6 +2,7 @@ class URLs { URLs._(); static const String appReleaseBuildNumber = "14"; + // static const host1 = "https://atomsm.hmg.com"; // production url static const host1 = "https://atomsmdev.hmg.com"; // local DEV url // static const host1 = "https://atomsmuat.hmg.com"; // local UAT url @@ -42,51 +43,94 @@ class URLs { static get getModels => "$_baseUrl/ModelDefinition/GetModelDefinitionAsset"; // get ?client=2 static get getAllRequestsAndCount => "$_baseUrl/CallRequest/GetAllRequestsAndCount"; // get //service request new flow urls. - static get nurseDashboardCountUrl=> '$_baseUrl/ServiceRequest/GetDashboardNurseCount'; - static get nurseDashboardDetailsUrl=> '$_baseUrl/ServiceRequest/GetDashboardNurseDetails'; - static get nurseRejectUrl=> '$_baseUrl/ServiceRequest/NurseReject'; - static get engineerStopTimer=> '$_baseUrl/ServiceRequest/EngineerStopTimer'; - static get nurseConfirmEngineerArrivedUrl=> '$_baseUrl/ServiceRequest/NurseConfirm'; - static get nurseConfirmUrl=> '$_baseUrl/ServiceRequest/NurseConfirm'; - static get nurseRejectEngineerArrivedUrl=> '$_baseUrl/ServiceRequest/NurseNotArrive'; - static get nurseConfirmEngineerArrivalUrl=> '$_baseUrl/ServiceRequest/NurseAccept'; - static get engineerDashboardCountUrl=> '$_baseUrl/ServiceRequest/GetDashboardEngineerCount'; - static get engineerDashboardDetailsUrl=> '$_baseUrl/ServiceRequest/GetDashboardEngineerDetails'; - static get engineerDashboardNotAssignDetails=> '$_baseUrl/ServiceRequest/GetDashboardEngineerNotAssignDetails'; - static get engineerDashboardUpcoming=> '$_baseUrl/ServiceRequest/GetDashboardEngineerUpcoming'; - static get engineerAcceptUrl=> '$_baseUrl/ServiceRequest/EngineerAccept'; - static get engineerAssignHimSelfUrl=> '$_baseUrl/ServiceRequest/AssignEngineerToHimself'; - static get engineerRejectUrl=> '$_baseUrl/ServiceRequest/EngineerReject'; - static get engineerFixRemotlyUrl=> '$_baseUrl/ServiceRequest/EngineerFixRemotly'; - static get engineerNeedVisitUrl=> '$_baseUrl/ServiceRequest/EngineerNeedVisit'; - static get engineerUpdateNeedVisitUrl=> '$_baseUrl/ServiceRequest/EngineerUpdateNeedVisit'; - static get engineerMarkAsFixUrl=> '$_baseUrl/ServiceRequest/EngineerMarkAsFix'; - static get reOrderActivity=> '$_baseUrl/ServiceRequest/ReOrderActivity'; - static get engineerConfirmArriveUrl=> '$_baseUrl/ServiceRequest/EngineerConfirmArrive'; - static get engineerUpdateWorkOrderUrl=> '$_baseUrl/ServiceRequest/EngineerUpdateWorkOrder'; - static get engineerSetReminderUrl=> '$_baseUrl/ServiceRequest/EngineerSetReminder'; - static get getWorkOrderByIdUrl=> '$_baseUrl/ServiceRequest/GetWorkOrderById'; - static get getQrCodeUrl=> '$_baseUrl/ServiceRequest/GetQRCode'; - static get deleteActivitySparePartUrl=> '$_baseUrl/ServiceRequest/DeleteActivitySparePart'; - static get deleteActivityMaintenanceUrl=> '$_baseUrl/ServiceRequest/DeleteActivityMaintenance'; - static get createActivitySparePartUrl=> '$_baseUrl/ServiceRequest/CreateActivitySparePart'; - static get createActivityMaintenanceUrl=> '$_baseUrl/ServiceRequest/CreateActivityMaintenance'; - static get createActivityAssetToBeRetiredUrl=> '$_baseUrl/ServiceRequest/CreateActivityAssetToBeRetired'; - static get createWorkOrderUrl=> '$_baseUrl/ServiceRequest/CreateWorkOrder'; - static get updateActivitySparePartUrl=> '$_baseUrl/ServiceRequest/UpdateActivitySparePart'; - static get updateActivityMaintenanceUrl=> '$_baseUrl/ServiceRequest/UpdateActivityMaintenance'; - static get assignEngineerToWorkOrderUrl=> '$_baseUrl/ServiceRequest/AssignEngineerToWorkOrder'; - static get getArrivalVerificationTypeUrl=> '$_baseUrl/ArrivalVerificationType/GetArrivalVerificationType'; - static get sendOtpUrl=> '$_baseUrl/SmsNotification/SendOTP/'; - static get verifyOtpUrl=> '$_baseUrl/SmsNotification/VerifyOTP/'; + static get nurseDashboardCountUrl => '$_baseUrl/ServiceRequest/GetDashboardNurseCount'; + + static get nurseDashboardDetailsUrl => '$_baseUrl/ServiceRequest/GetDashboardNurseDetails'; + + static get nurseRejectUrl => '$_baseUrl/ServiceRequest/NurseReject'; + + static get engineerStopTimer => '$_baseUrl/ServiceRequest/EngineerStopTimer'; + + static get nurseConfirmEngineerArrivedUrl => '$_baseUrl/ServiceRequest/NurseConfirm'; + + static get nurseConfirmUrl => '$_baseUrl/ServiceRequest/NurseConfirm'; + + static get nurseRejectEngineerArrivedUrl => '$_baseUrl/ServiceRequest/NurseNotArrive'; + + static get nurseConfirmEngineerArrivalUrl => '$_baseUrl/ServiceRequest/NurseAccept'; + + static get engineerDashboardCountUrl => '$_baseUrl/ServiceRequest/GetDashboardEngineerCount'; + + static get engineerDashboardDetailsUrl => '$_baseUrl/ServiceRequest/GetDashboardEngineerDetails'; + + static get engineerDashboardNotAssignDetails => '$_baseUrl/ServiceRequest/GetDashboardEngineerNotAssignDetails'; + + static get engineerDashboardUpcoming => '$_baseUrl/ServiceRequest/GetDashboardEngineerUpcoming'; + + static get engineerAcceptUrl => '$_baseUrl/ServiceRequest/EngineerAccept'; + + static get engineerAssignHimSelfUrl => '$_baseUrl/ServiceRequest/AssignEngineerToHimself'; + + static get engineerRejectUrl => '$_baseUrl/ServiceRequest/EngineerReject'; + + static get engineerFixRemotlyUrl => '$_baseUrl/ServiceRequest/EngineerFixRemotly'; + + static get engineerNeedVisitUrl => '$_baseUrl/ServiceRequest/EngineerNeedVisit'; + + static get engineerUpdateNeedVisitUrl => '$_baseUrl/ServiceRequest/EngineerUpdateNeedVisit'; + + static get engineerMarkAsFixUrl => '$_baseUrl/ServiceRequest/EngineerMarkAsFix'; + + static get reOrderActivity => '$_baseUrl/ServiceRequest/ReOrderActivity'; + + static get engineerConfirmArriveUrl => '$_baseUrl/ServiceRequest/EngineerConfirmArrive'; + + static get engineerUpdateWorkOrderUrl => '$_baseUrl/ServiceRequest/EngineerUpdateWorkOrder'; + + static get engineerSetReminderUrl => '$_baseUrl/ServiceRequest/EngineerSetReminder'; + + static get getWorkOrderByIdUrl => '$_baseUrl/ServiceRequest/GetWorkOrderById'; + + static get getQrCodeUrl => '$_baseUrl/ServiceRequest/GetQRCode'; + + static get deleteActivitySparePartUrl => '$_baseUrl/ServiceRequest/DeleteActivitySparePart'; + + static get deleteActivityMaintenanceUrl => '$_baseUrl/ServiceRequest/DeleteActivityMaintenance'; + + static get createActivitySparePartUrl => '$_baseUrl/ServiceRequest/CreateActivitySparePart'; + + static get createActivityMaintenanceUrl => '$_baseUrl/ServiceRequest/CreateActivityMaintenance'; + + static get createActivityAssetToBeRetiredUrl => '$_baseUrl/ServiceRequest/CreateActivityAssetToBeRetired'; + + static get createWorkOrderUrl => '$_baseUrl/ServiceRequest/CreateWorkOrder'; + + static get updateActivitySparePartUrl => '$_baseUrl/ServiceRequest/UpdateActivitySparePart'; + + static get updateActivityMaintenanceUrl => '$_baseUrl/ServiceRequest/UpdateActivityMaintenance'; + + static get assignEngineerToWorkOrderUrl => '$_baseUrl/ServiceRequest/AssignEngineerToWorkOrder'; + + static get uploadWorkOrderAttachmentsUrl => '$_baseUrl/ServiceRequest/UploadAttachmentsWorkOrder'; + + static get getArrivalVerificationTypeUrl => '$_baseUrl/ArrivalVerificationType/GetArrivalVerificationType'; + + static get sendOtpUrl => '$_baseUrl/SmsNotification/SendOTP/'; + + static get verifyOtpUrl => '$_baseUrl/SmsNotification/VerifyOTP/'; + // 08051 //Swipe module Api.. - static get swipeUrl=> '$_baseUrl/Swipe/Swipe'; - static get getSwipeLastTransactionUrl=> '$_baseUrl/Swipe/GetLastTransaction'; - static get getSwipeTransactionHistoryUrl=> '$_baseUrl/Swipe/GetTransactions'; + static get swipeUrl => '$_baseUrl/Swipe/Swipe'; + + static get getSwipeLastTransactionUrl => '$_baseUrl/Swipe/GetLastTransaction'; + + static get getSwipeTransactionHistoryUrl => '$_baseUrl/Swipe/GetTransactions'; + //Recurrent plan Api... - static get getRecurrentPlanByIdUrl=> '$_baseUrl/PlanRecurrentTasks/GetPlanRecurrentTaskById'; - static get updateRecurrentPlanUrl=> '$_baseUrl/PlanRecurrentTasks/UpdateTaskByEngineer'; + static get getRecurrentPlanByIdUrl => '$_baseUrl/PlanRecurrentTasks/GetPlanRecurrentTaskById'; + + static get updateRecurrentPlanUrl => '$_baseUrl/PlanRecurrentTasks/UpdateTaskByEngineer'; //Task request apis ... static get getTaskTypeByUserUrl=> '$_baseUrl/TaskTypes/GetTaskTypesByUser'; @@ -159,11 +203,17 @@ class URLs { static get getPpmService => "$_baseUrl/Lookups/GetLookup?lookupEnum=34"; // get for ppm po reason, in mobile there is no use of it. static get getServiceReportReasons => "$_baseUrl/Lookups/GetLookupReason?lookupEnum=505"; + static get getServiceReportRejectionReasons => "$_baseUrl/Lookups/GetLookup?lookupEnum=1303"; + static get getServiceReportReasonsNew => "$_baseUrl/Lookups/GetLookupReasonNew?lookupEnum=505"; + static get getServiceReportRetirementType => "$_baseUrl/Lookups/GetLookup?lookupEnum=415"; + static get getVisitReminderTimeValue => "$_baseUrl/Lookups/GetLookup?lookupEnum=1211"; + static get getServiceReportActivityStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=1302"; + static get getServiceReportTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=501"; // get static get getServiceReportTypesForWO => "$_baseUrl/Lookups/GetLookup?lookupEnum=34"; // get static get getServiceReportStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=521"; // get @@ -171,30 +221,39 @@ class URLs { static get getAssetTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=500"; // get static get getPersonRoles => "$_baseUrl/Lookups/GetLookup?lookupEnum=36"; // get static get getPartNumber => "$_baseUrl/PartCatalog/GetPartAutoComplete"; // get + static get getSparePartAvailableQuantity => "$_baseUrl/SparePart/GetAvailablityQtyForSparePartByPartId"; // get static get getServiceReportPriority => "$_baseUrl/Lookups/GetLookup?lookupEnum=4"; // get static get getServiceReportDefectTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=601"; // get static get getCallRequestForWorkOrder => "$_baseUrl/CallRequest/GetCallRequestForWorkOrder"; // get static get attachmentBaseUrl => "https://atomsmdev.hmg.com/v2/mobile/Files/DownloadFile?fileName="; + //gas refill 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 requestGasRefill => "$_baseUrl/GasRefill/AddGasRefillFromMobile"; // get static get updateGasRefill => "$_baseUrl/GazRefill/UpdateGazRefill"; // get static get getGasRefill => "$_baseUrl/GazRefill/GetGazRefills"; // get - static get getGasRefillById => "$_baseUrl/GazRefill/GetGazRefillById"; // get + // static get getGasRefillById => "$_baseUrl/GazRefill/GetGazRefillById"; // get older endpoint.. + static get getGasRefillById => "$_baseUrl/GasRefill/GetGasRefillById"; // get static get getGazRefillComments => "$_baseUrl/GazRefill/GetHistoryComments"; // get static get addGazRefillComment => "$_baseUrl/GazRefill/AddHistoryComment"; // add + static get updateGasRefillByEngineer => "$_baseUrl/GasRefill/UpdateGasRefillByEngineer"; // update //device transfer static get requestDeviceTransfer => "$_baseUrl/AssetTransfer/AddAssetTransfer"; // get - static get updateDeviceTransfer => "$_baseUrl/AssetTransfer/UpdateAssetTransfer"; // get + // static get updateDeviceTransfer => "$_baseUrl/AssetTransfer/UpdateAssetTransfer"; // get static get getDeviceTransfer => "$_baseUrl/AssetTransfer/GetAssetTransfers"; // get - static get getAssetTransferById => "$_baseUrl/AssetTransfer/GetAssetTransferById"; // get + // static get getAssetTransferById => "$_baseUrl/AssetTransfer/GetAssetTransferById"; // get static get getAssetTransferStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=406"; // get + //Asset transfer new Apis + static get getAssetTransferById => "$_baseUrl/AssetTransfer/GetAssetTransferNewById"; // get + static get createAssetTransferRequest => "$_baseUrl/AssetTransfer/AddAssetTransferMobileNew"; // post + static get updateDeviceTransfer => "$_baseUrl/AssetTransfer/UpdateEngineerAssetTransferNew"; // get + // employee static get getEmployees => "$_baseUrl/Lookups/GetLookup?lookupEnum=33"; // get static get getEngineers => "$_baseUrl/Account/GetUserByRoleValue?value=R-6"; // get diff --git a/lib/controllers/providers/api/all_requests_provider.dart b/lib/controllers/providers/api/all_requests_provider.dart index 80ef147b..77e01375 100644 --- a/lib/controllers/providers/api/all_requests_provider.dart +++ b/lib/controllers/providers/api/all_requests_provider.dart @@ -4,7 +4,6 @@ import 'package:flutter/widgets.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/extensions/context_extension.dart'; import 'package:test_sa/models/all_requests_and_count_model.dart'; import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/ppm/recurrent_wo.dart'; @@ -62,7 +61,7 @@ class AllRequestsProvider extends ChangeNotifier { // AllRequestsAndCount? get completedRequests => _completedRequests; AllRequestsAndCount? get requestDetailList => _requestDetailList; - RecurrentWoData? _recurrentWoData=RecurrentWoData(); + RecurrentWoData? _recurrentWoData = RecurrentWoData(); RecurrentWoData? get recurrentWoData => _recurrentWoData; @@ -201,6 +200,15 @@ class AllRequestsProvider extends ChangeNotifier { stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { recurrentWoData = RecurrentWoData.fromJson(json.decode(response.body)["data"]); + recurrentWoData?.planRecurrentMedicalTaskRooms?.forEach((element) { + element.planRecurrentMedicalTaskRoomTabs?.forEach((tabs) { + tabs.planRecurrentMedicalTaskRoomTabAttributes?.forEach((attribute) { + if (attribute.attribute?.type == "bool" && attribute.attributeValue == null) { + attribute.attributeValue = "true"; + } + }); + }); + }); notifyListeners(); } isLoading = false; diff --git a/lib/controllers/providers/api/asset_transfer_provider.dart b/lib/controllers/providers/api/asset_transfer_provider.dart index 7f722ddf..b4cad354 100644 --- a/lib/controllers/providers/api/asset_transfer_provider.dart +++ b/lib/controllers/providers/api/asset_transfer_provider.dart @@ -6,8 +6,10 @@ 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/extensions/context_extension.dart'; +import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/models/device/asset.dart'; import 'package:test_sa/models/device/asset_transfer.dart'; +import 'package:test_sa/models/service_request/pending_service_request_model.dart'; import 'package:test_sa/models/user.dart'; import '../../../models/hospital.dart'; @@ -120,15 +122,27 @@ class AssetTransferProvider extends ChangeNotifier { } } + Future checkAssetPendingRequest(int assetId) async { + Response response; + try { + response = await ApiManager.instance.post(URLs.CheckIfAssetHasAnotherServiceRequest + "?assetId=$assetId",body: {}); + stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) {} + return PendingAssetServiceRequest.fromJson(json.decode(response.body)["data"]); + } catch (error) { + "Please Try Again\n$error".addTranslation.showToast; + return null; + } + } + Future createRequest({ required BuildContext context, - required AssetTransfer assetDestination, - required Asset asset, + required AssetTransfer model, }) async { Response response; try { showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); - response = await ApiManager.instance.post(URLs.requestDeviceTransfer, body: assetDestination.transferBody(asset: asset)); + response = await ApiManager.instance.post(URLs.createAssetTransferRequest, body: model.toCreateAssetTransferJson()); stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { if (items != null) { @@ -148,29 +162,15 @@ class AssetTransferProvider extends ChangeNotifier { } } - Future updateRequest(BuildContext context, {required AssetTransfer assetTransfer, required bool isSender}) async { + Future updateRequest(BuildContext context, {required AssetTransfer model}) async { Response response; try { showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); - response = await ApiManager.instance.put(URLs.updateDeviceTransfer, body: assetTransfer.toJson()); - - //print(response.body); - // print("${newModel.engSignature}.png"); - // response = await post( - // Uri.parse("$host${URLs.updateDeviceTransfer}/$requestId"), - // body: body, - // ); - + response = await ApiManager.instance.post(URLs.updateDeviceTransfer, body: model.toEngineerUpdateJson()); stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { reset(); - // Fluttertoast.showToast(msg: context.translation.successfulRequestMessage); Navigator.of(context).pop(); - // oldModel.fromDeviceTransfer( - // DeviceTransfer.fromJson( - // json.decode(utf8.decode(response.bodyBytes))[0] - // ) - // ); notifyListeners(); } else { Fluttertoast.showToast(msg: "${context.translation.failedToCompleteRequest} :${json.decode(response.body)['message']}"); @@ -184,8 +184,5 @@ class AssetTransferProvider extends ChangeNotifier { } } - bool _isLocalUrl(String? url) { - if (url?.isEmpty ?? true) return false; - return url!.startsWith("/") || url.startsWith("file://") || url.substring(1).startsWith(':\\'); - } + } diff --git a/lib/controllers/providers/api/gas_refill_provider.dart b/lib/controllers/providers/api/gas_refill_provider.dart index a5d59016..84c967b7 100644 --- a/lib/controllers/providers/api/gas_refill_provider.dart +++ b/lib/controllers/providers/api/gas_refill_provider.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'dart:developer'; +import 'dart:io'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; @@ -9,6 +10,7 @@ import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/models/hospital.dart'; import 'package:test_sa/models/new_models/gas_refill_model.dart'; +import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/models/user.dart'; import '../../../new_views/common_widgets/app_lazy_loading.dart'; @@ -44,12 +46,15 @@ class GasRefillProvider extends ChangeNotifier { // failed _loading = false bool isLoading = false; + + Future getGasRefillObjectById(num id) async { try { - Response response = await ApiManager.instance.get(URLs.getGasRefillById + "?gazRefillId=$id"); + Response response = await ApiManager.instance.get(URLs.getGasRefillById + "?gasRefillId=$id"); if (response.statusCode >= 200 && response.statusCode < 300) { - return GasRefillModel.fromJson(json.decode(response.body)["data"]); + + return GasRefillModel.fromJson(json.decode(response.body)["data"]); } else { return null; } @@ -58,6 +63,7 @@ class GasRefillProvider extends ChangeNotifier { } } + /// 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 @@ -105,20 +111,14 @@ class GasRefillProvider extends ChangeNotifier { } } - Future createModel({ + Future addGasRefillRequest({ required BuildContext context, - required User user, required GasRefillModel model, }) async { late Response response; try { showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); - final Map body = { - "uid": user.id.toString(), - "token": user.token ?? "", - }; - body.addAll(model.toJson()); - response = await ApiManager.instance.post(URLs.requestGasRefill, body: body); + response = await ApiManager.instance.post(URLs.requestGasRefill, body: model.toJson()); stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { if (items != null) { @@ -137,6 +137,23 @@ class GasRefillProvider extends ChangeNotifier { } } + Future updateGasRefill({required int status, required GasRefillModel model}) async { + isLoading = true; + Response response; + try { + response = await ApiManager.instance.post(URLs.updateGasRefillByEngineer, body: model.toUpdateEngineerPayload(status: status)); + stateCode = response.statusCode; + isLoading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + isLoading = false; + stateCode = -1; + notifyListeners(); + return -1; + } + } + Future updateModel({ required String host, required User user, @@ -145,7 +162,7 @@ class GasRefillProvider extends ChangeNotifier { }) async { Map body = { "id": newModel.id, - "gazRefillNo": newModel.gazRefillNo ?? "", + "gasRefillNo": newModel.gasRefillNo ?? "", "status": newModel.status?.toJson(), //"expectedDate": newModel.expectedDate?.toIso8601String(), "expectedTime": newModel.expectedDate, @@ -164,7 +181,7 @@ class GasRefillProvider extends ChangeNotifier { "comment": newModel.comment, }; - body["gazRefillDetails"] = newModel.gazRefillDetails! + body["gasRefillDetails"] = newModel.gasRefillDetails! .map((model) => { "gasType": model.gasType?.toJson(), "cylinderSize": model.cylinderSize?.toJson(), diff --git a/lib/controllers/providers/api/parts_provider.dart b/lib/controllers/providers/api/parts_provider.dart index 7ec4d8fc..fc2829b8 100644 --- a/lib/controllers/providers/api/parts_provider.dart +++ b/lib/controllers/providers/api/parts_provider.dart @@ -96,11 +96,29 @@ class PartsProvider extends ChangeNotifier { if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received List categoriesListJson = json.decode(response.body)["data"]; - page = categoriesListJson.map((part) => SparePart.fromJson(part)).toList(); + page = categoriesListJson.map((part) => SparePart.fromJson(part,false)).toList(); } return page; } catch (error) { return []; } } + // Implement this only for spare part request for now show and search on display name .... + + Future> getPartsListByDisplayName({num? assetId, String? displayName}) async { + late Response response; + try { + response = await ApiManager.instance.post(URLs.getPartNumber, body: {"displayName": displayName, }); + 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((part) => SparePart.fromJson(part,true)).toList(); + } + return page; + } catch (error) { + return []; + } + } + } diff --git a/lib/controllers/providers/api/ppm_provider.dart b/lib/controllers/providers/api/ppm_provider.dart index 0af12483..ea5dc266 100644 --- a/lib/controllers/providers/api/ppm_provider.dart +++ b/lib/controllers/providers/api/ppm_provider.dart @@ -22,6 +22,14 @@ class PpmProvider extends ChangeNotifier { PlanPreventiveVisit? _planPreventiveVisit; late int _totalTabs = 4; TabController? tabController; + bool _isReadOnly = false; + + bool get isReadOnly => _isReadOnly; + + set isReadOnly(bool value) { + _isReadOnly = value; + notifyListeners(); + } int get totalTabs => _totalTabs; @@ -155,6 +163,11 @@ class PpmProvider extends ChangeNotifier { if (response.statusCode >= 200 && response.statusCode < 300) { ppmPlanAttachments = []; planPreventiveVisit = PlanPreventiveVisit.fromJson(json.decode(response.body)["data"]); + if(planPreventiveVisit?.visitStatus?.value! == 1 || planPreventiveVisit?.visitStatus?.value == 3){ + isReadOnly =true; + }else{ + isReadOnly =false; + } isLoading = false; notifyListeners(); return planPreventiveVisit; diff --git a/lib/dashboard_latest/dashboard_provider.dart b/lib/dashboard_latest/dashboard_provider.dart index d763092d..db07f571 100644 --- a/lib/dashboard_latest/dashboard_provider.dart +++ b/lib/dashboard_latest/dashboard_provider.dart @@ -367,16 +367,16 @@ class CategoryTabs { if (userType == UsersTypes.engineer) { // tabs.add(CategoryTabs(label: 'Upcoming', tag: 0, id: 0)); // tabs.add(CategoryTabs('Open', 1)); - tabs.add(CategoryTabs(label: 'UnAssigned Open', tag: 1, id: 1)); - tabs.add(CategoryTabs(label: 'Assigned Open', tag: 1, id: 2)); + tabs.add(CategoryTabs(label: 'UnAssigned', tag: 1, id: 1)); + tabs.add(CategoryTabs(label: 'Open', tag: 1, id: 2)); tabs.add(CategoryTabs(label: 'In Progress', tag: 2, id: 3)); tabs.add(CategoryTabs(label: 'Completed', tag: 3, id: 4)); return tabs; } - tabs.add(CategoryTabs(label: 'Open Request', tag: 1, id: 2)); + tabs.add(CategoryTabs(label: 'Open', tag: 1, id: 2)); tabs.add(CategoryTabs(label: 'In Progress', tag: 2, id: 3)); - tabs.add(CategoryTabs(label: 'Upcoming', tag: 3, id: 1)); + tabs.add(CategoryTabs(label: 'Pending Acknowledgement', tag: 3, id: 1)); tabs.add(CategoryTabs(label: 'Canceled', tag: 6, id: 4)); return tabs; } diff --git a/lib/dashboard_latest/widgets/progress_fragment.dart b/lib/dashboard_latest/widgets/progress_fragment.dart index 994d13d7..8f60be60 100644 --- a/lib/dashboard_latest/widgets/progress_fragment.dart +++ b/lib/dashboard_latest/widgets/progress_fragment.dart @@ -151,10 +151,9 @@ // import 'package:flutter/material.dart'; +import 'package:pie_chart/pie_chart.dart'; import 'package:provider/provider.dart'; -import 'package:syncfusion_flutter_charts/charts.dart'; import 'package:test_sa/dashboard_latest/dashboard_provider.dart'; -import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; @@ -212,46 +211,44 @@ class ProgressFragment extends StatelessWidget { child: Stack( alignment: Alignment.center, children: [ - SfCircularChart( - tooltipBehavior: TooltipBehavior( - enable: true, - // elevation: 2, - color: context.isDark ? const Color(0xFF111427) : const Color(0xffF7F9FB), - textStyle: context.isDark ? null : const TextStyle(color: Colors.black87, fontSize: 12), + PieChart( + dataMap: {for (var v in chartData) v.x: v.y}, + animationDuration: const Duration(milliseconds: 800), + chartLegendSpacing: 32, + chartRadius: MediaQuery.of(context).size.width / 3.2, + colorList: chartData.map((element) => element.color).toList(), + initialAngleInDegree: 270, + chartType: ChartType.ring, + ringStrokeWidth: 32, + centerWidget: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + context.translation.total, + style: AppTextStyles.heading5.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ), + Text( + "$total", + style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), + ), + ], + ), + legendOptions: const LegendOptions( + showLegendsInRow: false, + legendPosition: LegendPosition.right, + showLegends: true, + legendTextStyle: TextStyle( + fontWeight: FontWeight.w500, ), - legend: const Legend( - //isVisible: true, - ), - series: [ - DoughnutSeries( - dataSource: chartData, - radius: "100%", - innerRadius: "60%", - pointColorMapper: (ChartData data, _) => data.color, - xValueMapper: (ChartData data, _) => data.x, - yValueMapper: (ChartData data, _) => data.y, - dataLabelMapper: (ChartData data, _) => data.x, - dataLabelSettings: DataLabelSettings( - margin: const EdgeInsets.all(8), - isVisible: true, - textStyle: TextStyle(color: context.isDark ? Colors.white : AppColor.neutral20, fontSize: 12, fontWeight: FontWeight.w500), - labelPosition: ChartDataLabelPosition.outside, - ), - ) - ]).toShimmer(isShow: snapshot.isAllCountLoading, radius: 250).paddingAll(0).toShadowContainer(context), - Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - context.translation.total, - style: AppTextStyles.heading5.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), - ), - Text( - "$total", - style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20), - ), - ], - ), + ), + chartValuesOptions: const ChartValuesOptions( + showChartValueBackground: false, + showChartValues: false, + showChartValuesInPercentage: false, + showChartValuesOutside: false, + decimalPlaces: 1, + ), + ).toShimmer(isShow: snapshot.isAllCountLoading, radius: 250).paddingAll(0).toShadowContainer(context), ], ), ), diff --git a/lib/extensions/text_extensions.dart b/lib/extensions/text_extensions.dart index 5a81bc5c..ea5496e3 100644 --- a/lib/extensions/text_extensions.dart +++ b/lib/extensions/text_extensions.dart @@ -164,13 +164,14 @@ extension CapExtension on String { String get allInCaps => toUpperCase(); - String get cleanupWhitespace => replaceAll(RegExp(r"\s+"), " "); - - String get capitalizeFirstOfEach => trim().isNotEmpty - ? trim().toLowerCase().split(" ").map((str) { - return str.trim()?.inCaps ?? ""; - }).join(" ") - : ""; + String get cleanupWhitespace => this;//replaceAll(RegExp(r"\s+"), " "); + + String get capitalizeFirstOfEach => this; + //trim().isNotEmpty + // ? trim().toLowerCase().split(" ").map((str) { + // return str.trim()?.inCaps ?? ""; + // }).join(" ") + // : ""; } extension FilesExtension on String { diff --git a/lib/extensions/widget_extensions.dart b/lib/extensions/widget_extensions.dart index 9cce960f..f13316a2 100644 --- a/lib/extensions/widget_extensions.dart +++ b/lib/extensions/widget_extensions.dart @@ -4,6 +4,7 @@ import 'package:shimmer/shimmer.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/new_views/swipe_module/dialoge/acknowledge_work_dialog.dart'; import '../new_views/app_style/app_color.dart'; @@ -54,6 +55,26 @@ extension WidgetExtensions on Widget { Widget toExpanded({int flex = 1}) => Expanded(flex: flex, child: this); + Widget handlePopScope({required BuildContext cxt, required VoidCallback onSave, bool? showPopUp =true}) { + return showPopUp! ? PopScope( + canPop: false, + onPopInvokedWithResult: (didPop, result) { + if (didPop) { + return; + } + showDialog( + context: cxt, + builder: (BuildContext cxt) => AcknowledgeWorkDialog( + onSave: () => onSave(), + onDiscard: () { + Navigator.of(cxt).pop(); + }, + ), + ); + }, + child: this): this; + } + Widget toShimmer({bool isShow = true, double radius = 20}) => isShow ? Shimmer.fromColors( baseColor: const Color(0xffe8eff0), diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index 526e0647..a2263cf3 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -560,6 +560,16 @@ "installationBuilding": "مبنى التركيب", "installationFloor": "طابق التركيب", "installationDepartment": "قسم التركيب", - "acknowledge": "إقرار" + "acknowledge": "إقرار", + "transferAsset": "نقل الأصل", + "createAssetTransferRequest": "إنشاء طلب نقل أصل", + + "arrivedDate": "تاريخ الوصول", + "closedDate": "تاريخ الإغلاق", + "since": "منذ", + "rejectionDetails": "تفاصيل الرفض", + "part": "جزء", + "closedDate": "تاريخ الإغلاق", + "creationDate": "تاريخ الإنشاء" } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 89ce0bcd..ff811730 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -563,5 +563,15 @@ "installationBuilding": "Installation Building", "installationFloor": "Installation Floor", "installationDepartment": "Installation Department", - "acknowledge": "Acknowledge" + "acknowledge": "Acknowledge", + "transferAsset": "Transfer Asset", + "createAssetTransferRequest": "Create Asset Transfer Request", + "telephone": "Telephone", + "arrivedDate": "Arrived Date", + "closedDate": "Closed Date", + "since": "Since", + "rejectionDetails": "Rejection Details", + "part": "Part", + "closedDate": "Closed Date", + "creationDate": "Creation Date" } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 5f5ccd1a..1629a3c4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -70,9 +70,10 @@ import 'package:test_sa/service_request_latest/service_request_detail_provider.d import 'package:test_sa/service_request_latest/views/nurse/create_new_request_view.dart'; import 'package:test_sa/views/pages/device_transfer/asset_filter_screen.dart'; import 'package:test_sa/views/pages/device_transfer/asset_search_screen.dart'; -import 'package:test_sa/views/pages/device_transfer/request_device_transfer.dart'; +import 'package:test_sa/views/pages/device_transfer/create__asset_transfer_request.dart'; import 'package:test_sa/views/pages/device_transfer/track_device_transfer.dart'; import 'package:test_sa/views/pages/sub_workorder/create_sub_workorder_page.dart'; +import 'package:test_sa/views/pages/user/gas_refill/gas_refill_form.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'; @@ -308,6 +309,7 @@ class MyApp extends StatelessWidget { CreateTaskView.id: (_) => const CreateTaskView(), //ReportIssuesPage.id: (_) => ReportIssuesPage(), RequestGasRefill.id: (_) => const RequestGasRefill(), + GasRefillForm.id: (_) => const GasRefillForm(), CreateServiceRequestPage.id: (_) => const CreateServiceRequestPage(), CreateNewRequest.id: (_) => const CreateNewRequest(), // SingleHospitalPicker.id: (_) => SingleHospitalPicker(), @@ -318,7 +320,7 @@ class MyApp extends StatelessWidget { // PreventiveMaintenanceVisitsPage.id: (_) => PreventiveMaintenanceVisitsPage(), PpmPage.id: (_) => const PpmPage(), TrackGasRefillPage.id: (_) => const TrackGasRefillPage(), - RequestDeviceTransfer.id: (_) => const RequestDeviceTransfer(), + CreateAssetTransferRequest.id: (_) => const CreateAssetTransferRequest(), TrackDeviceTransferPage.id: (_) => const TrackDeviceTransferPage(), // todo remove this class after work diff --git a/lib/models/device/asset_transfer.dart b/lib/models/device/asset_transfer.dart index 40ae2302..db4c9900 100644 --- a/lib/models/device/asset_transfer.dart +++ b/lib/models/device/asset_transfer.dart @@ -2,86 +2,100 @@ import 'package:flutter/src/widgets/framework.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/models/device/asset.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/new_models/assistant_employee.dart'; import 'package:test_sa/models/ppm/ppm.dart'; import 'package:test_sa/models/timer_model.dart'; import 'asset_transfer_attachment.dart'; class AssetTransfer { - AssetTransfer( - {this.id, - this.transferNo, - this.transferCode, - this.assetId, - this.destSiteId, - this.destBuildingId, - this.destFloorId, - this.destDepartmentId, - this.destRoomId, - this.senderSiteId, - this.senderBuildingId, - this.senderFloorId, - this.senderDepartmentId, - this.senderRoom, - this.senderAssignedEmployeeId, - this.senderMachineStatusId, - this.senderComment, - this.comment, - this.receiverEndUserId, - this.receiverEndUserName, - this.senderStartDate, - this.senderEndDate, - this.senderWorkingHours, - this.senderTravelingHours, - this.senderEngSignature, - this.senderAttachments, - this.receiverAssignedEmployeeId, - this.receiverMachineStatusId, - this.receiverComment, - this.receiverStartDate, - this.receiverEndDate, - this.receiverWorkingHours, - this.receiverTravelingHours, - this.receiverEngSignature, - this.receiverAttachments, - this.assetNumber, - this.assetName, - this.manufacturerName, - this.modelName, - this.assetSerialNo, - this.destDepartmentName, - this.destBuildingName, - this.applied, - this.extensionNo, - this.name, - this.employeeId, - this.createdDate, - this.createdOn, - this.destFloorName, - this.destSiteName, - this.manufacturerId, - this.modelId, - this.modifiedOn, - this.receiverAssignedEmployeeName, - this.receiverEngSignatureUrl, - this.receiverMachineStatusName, - this.senderAssignedEmployeeName, - this.senderBuildingName, - this.senderDepartmentName, - this.senderEngSignatureUrl, - this.senderFloorName, - this.senderMachineStatusName, - this.senderSiteName, - this.supplierId, - this.supplierName, - this.senderVisitTimers, - this.receiverVisitTimers, - this.tbsTimer}); + AssetTransfer({ + this.id, + this.transferNo, + this.transferType, + this.transferCode, + this.assetId, + this.destSiteId, + this.destBuildingId, + this.destFloorId, + this.destDepartmentId, + this.destRoomId, + this.senderSiteId, + this.senderBuildingId, + this.senderFloorId, + this.senderDepartmentId, + this.senderRoom, + this.senderAssignedEmployeeId, + this.senderMachineStatusId, + this.senderComment, + this.comment, + this.receiverEndUserId, + this.receiverEndUserName, + this.senderStartDate, + this.senderEndDate, + this.senderWorkingHours, + this.senderTravelingHours, + this.senderEngSignature, + this.senderAttachments, + this.receiverAssignedEmployeeId, + this.receiverMachineStatusId, + this.receiverComment, + this.receiverStartDate, + this.receiverEndDate, + this.receiverWorkingHours, + this.receiverTravelingHours, + this.receiverEngSignature, + this.receiverAttachments, + this.attachments, + this.assetNumber, + this.assetName, + this.manufacturerName, + this.modelName, + this.assetSerialNo, + this.destDepartmentName, + this.destBuildingName, + this.applied, + this.isSender, + this.extensionNo, + this.name, + this.employeeId, + this.createdDate, + this.createdOn, + this.destFloorName, + this.destSiteName, + this.manufacturerId, + this.modelId, + this.modifiedOn, + this.receiverAssignedEmployeeName, + this.receiverEngSignatureUrl, + this.receiverMachineStatusName, + this.senderAssignedEmployeeName, + this.senderBuildingName, + this.senderDepartmentName, + this.senderEngSignatureUrl, + this.senderFloorName, + this.senderMachineStatusName, + this.senderSiteName, + this.supplierId, + this.supplierName, + this.senderVisitTimers, + this.receiverVisitTimers, + this.assetTransferEngineerTimers, + this.tbsTimer, + this.timerModelList, + this.assistantEmployees, + this.modelAssistantEmployees, + this.assetTransferAssistantEmployeesReceiver, + this.assetTransferAssistantEmployeesSender, + this.statusValue, + }); AssetTransfer.fromJson(dynamic json) { id = json['id']; transferNo = json['transferNo']; transferCode = json['transferCode']; + transferType = json["transferType"] == null ? null : Lookup.fromJson(json["transferType"]); assetId = json['assetId']; destSiteId = json['destSiteId']; destBuildingId = json['destBuildingId']; @@ -130,6 +144,19 @@ class AssetTransfer { receiverVisitTimers!.add(VisitTimers.fromJson(v)); }); } + if (json['assetTransferAssistantEmployeesSender'] != null) { + assetTransferAssistantEmployeesSender = []; + json['assetTransferAssistantEmployeesSender'].forEach((v) { + assetTransferAssistantEmployeesSender!.add(AssetTransferAssistantEmployees.fromJson(v)); + }); + } + if (json['assetTransferAssistantEmployeesReceiver'] != null) { + assetTransferAssistantEmployeesReceiver = []; + json['assetTransferAssistantEmployeesReceiver'].forEach((v) { + assetTransferAssistantEmployeesReceiver!.add(AssetTransferAssistantEmployees.fromJson(v)); + }); + } + tbsTimer = TimerModel(); // try { // receiverTimer = TimerModel(startAt: DateTime.tryParse(receiverStartDate ?? ""), endAt: DateTime.tryParse(receiverEndDate ?? "")); @@ -151,6 +178,13 @@ class AssetTransfer { receiverAttachments!.add(AssetTransferAttachment.fromJson(v)); }); } + if (senderAttachments != null) { + attachments = senderAttachments; + } else if (receiverAttachments != null) { + attachments = receiverAttachments; + } + print('sender attachment i got is ${senderAttachments?.length}'); + assetNumber = json['assetNumber']; assetName = json['assetName']; manufacturerName = json['manufacturerName']; @@ -186,6 +220,8 @@ class AssetTransfer { num? id; num? transferNo; String? transferCode; + int? statusValue; + Lookup? transferType; String? assetSerialNo; num? assetId; String? assetNumber; @@ -216,6 +252,7 @@ class AssetTransfer { String? senderTravelingHours; String? senderEngSignature; List? senderAttachments; + List? attachments; String? receiverAssignedEmployeeId; num? receiverMachineStatusId; String? receiverComment; @@ -242,6 +279,7 @@ class AssetTransfer { String? receiverMachineStatusName; String? receiverEngSignatureUrl; bool? applied; + bool? isSender; dynamic extensionNo; String? employeeId; String? name; @@ -250,12 +288,21 @@ class AssetTransfer { String? modifiedOn; List? senderVisitTimers; List? receiverVisitTimers; + List? assetTransferEngineerTimers; + List? timerModelList = []; + List? assistantEmployees; + List? assetTransferAssistantEmployeesSender; + + List? assetTransferAssistantEmployeesReceiver; + + AssetTransferAssistantEmployees? modelAssistantEmployees; TimerModel? tbsTimer = TimerModel(); AssetTransfer copyWith( {num? id, num? transferNo, String? transferCode, + Lookup? transferType, num? assetId, num? destSiteId, num? destBuildingId, @@ -326,6 +373,7 @@ class AssetTransfer { id: id ?? this.id, transferNo: transferNo ?? this.transferNo, transferCode: transferCode ?? this.transferCode, + transferType: transferType ?? this.transferType, assetId: assetId ?? this.assetId, destSiteId: destSiteId ?? this.destSiteId, destBuildingId: destBuildingId ?? this.destBuildingId, @@ -375,10 +423,10 @@ class AssetTransfer { receiverMachineStatusName: receiverMachineStatusName ?? this.receiverMachineStatusName, receiverEngSignatureUrl: receiverEngSignatureUrl ?? this.receiverEngSignatureUrl, applied: applied ?? this.applied, - extensionNo: extensionNo??this.extensionNo, - employeeId: employeeId??this.employeeId, - name: name??this.name, - createdDate: createdDate??this.createdDate, + extensionNo: extensionNo ?? this.extensionNo, + employeeId: employeeId ?? this.employeeId, + name: name ?? this.name, + createdDate: createdDate ?? this.createdDate, createdOn: createdOn ?? this.createdOn, modifiedOn: modifiedOn ?? this.modifiedOn, assetSerialNo: assetSerialNo ?? this.assetSerialNo, @@ -472,6 +520,48 @@ class AssetTransfer { return map; } + Map toCreateAssetTransferJson() { + final map = {}; + map['id'] = id; + map['assetId'] = assetId; + map['transferTypeId'] = transferType?.id; + map['destSiteId'] = destSiteId; + map['destSiteId'] = destSiteId; + map['destBuildingId'] = destBuildingId; + map['destFloorId'] = destFloorId; + map['destDepartmentId'] = destDepartmentId; + map['destRoomId'] = destRoomId; + map['comment'] = comment; + if (attachments != null) { + map['attachments'] = attachments!.map((v) => v.toJson()).toList(); + } + return map; + } + + Map toEngineerUpdateJson() { + final map = {}; + map['id'] = id; + map['statusValue'] = statusValue; + map['isSender'] = isSender; + map['techComment'] = isSender! ? senderComment : receiverComment; + map['assetTransferAssistantEmployees'] = modelAssistantEmployees; + map['assetTransferEngineerTimers'] = assetTransferEngineerTimers; + if (attachments != null) { + map['attachments'] = attachments!.map((v) => v.toJson()).toList(); + } + if (assetTransferEngineerTimers != null) { + map['assetTransferEngineerTimers'] = assetTransferEngineerTimers!.map((v) => v.toJson()).toList(); + } + if (modelAssistantEmployees != null) { + if (modelAssistantEmployees!.employeeId != null) { + map['assetTransferAssistantEmployees'] = [modelAssistantEmployees!.toJson()]; + } else { + map['assetTransferAssistantEmployees'] = []; + } + } + return map; + } + Map transferBody({Asset? asset}) { final map = {}; map['id'] = 0; @@ -526,6 +616,7 @@ class AssetTransfer { if (assetTransfer == null) return; id = assetTransfer.id; transferNo = assetTransfer.transferNo; + transferType = assetTransfer.transferType; transferCode = assetTransfer.transferCode; assetId = assetTransfer.assetId; destSiteId = assetTransfer.destSiteId; @@ -591,6 +682,8 @@ class AssetTransfer { manufacturerName = assetTransfer.manufacturerName; senderVisitTimers = assetTransfer.senderVisitTimers; receiverVisitTimers = assetTransfer.receiverVisitTimers; + assetTransferAssistantEmployeesReceiver = assetTransfer.assetTransferAssistantEmployeesReceiver; + assetTransferAssistantEmployeesSender = assetTransfer.assetTransferAssistantEmployeesSender; } Future validate(BuildContext context) async { @@ -613,3 +706,42 @@ class AssetTransfer { return true; } } + +class AssetTransferAssistantEmployees { + DateTime? startDate; + DateTime? endDate; + double? workingHours; + String? techComment; + String? employeeId; + String? employeeNumber; + String? employeeName; + String? email; + String? mobileNo; + dynamic extension; + + AssetTransferAssistantEmployees( + {this.startDate, this.endDate, this.workingHours, this.techComment, this.employeeId, this.employeeName, this.employeeNumber, this.email, this.extension, this.mobileNo}); + + AssetTransferAssistantEmployees.fromJson(Map json) { + startDate = json['startDate'] != null ? DateTime.parse(json['startDate']) : null; + endDate = json['endDate'] != null ? DateTime.parse(json['endDate']) : null; + workingHours = json['workingHours']; + techComment = json['techComment']; + employeeId = json['employeeId']; + employeeNumber = json['employeeNumber']; + employeeName = json['employeeName']; + email = json['email']; + mobileNo = json['mobileNo']; + extension = json['extension']; + } + + Map toJson() { + final Map data = {}; + data['startDate'] = startDate?.toIso8601String(); + data['endDate'] = endDate?.toIso8601String(); + data['workingHours'] = workingHours; + data['techComment'] = techComment; + data['employeeId'] = employeeId; + return data; + } +} diff --git a/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart b/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart index 046cf913..9580c1a9 100644 --- a/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart +++ b/lib/models/helper_data_models/maintenance_request/activity_maintenance_model.dart @@ -12,7 +12,6 @@ class ActivityMaintenanceHelperModel { //remove this int? lastSituationId; Lookup? lastSituation; - Lookup? activityStatus; DateTime? startTime; DateTime? endTime; diff --git a/lib/models/helper_data_models/workorder/work_order_helper_models.dart b/lib/models/helper_data_models/workorder/work_order_helper_models.dart index f851e5c3..a1fcdc26 100644 --- a/lib/models/helper_data_models/workorder/work_order_helper_models.dart +++ b/lib/models/helper_data_models/workorder/work_order_helper_models.dart @@ -41,6 +41,14 @@ class WorkOrderHelperModel { } return data; } + Map toUploadAttachmentJson(int? workOrderId,List? workOrderAttachments) { + final Map data = {}; + data['workOrderId'] = workOrderId; + if (workOrderAttachments != null) { + data['workOrderAttachments'] = workOrderAttachments!.map((v) => v.toJson()).toList(); + } + return data; + } } class WorkOrderAttachments { @@ -73,6 +81,7 @@ class EngineerUpdateWorkOrderHelperModel { Lookup? failureReason; FaultDescription? faultDescription; String? solution; + String? callResponse; EngineerUpdateWorkOrderHelperModel({ this.workOrderId, @@ -85,6 +94,7 @@ class EngineerUpdateWorkOrderHelperModel { this.serviceType, this.solution, this.returnToService, + this.callResponse, }); Map toJson() { @@ -96,6 +106,7 @@ class EngineerUpdateWorkOrderHelperModel { data['loanAssetId'] = loanAssetId; data['failureReasonId'] = failureReason?.id; data['faultDescriptionId'] = faultDescription?.id; + data['callResponse'] = callResponse; return data; } } diff --git a/lib/models/new_models/assistant_employee.dart b/lib/models/new_models/assistant_employee.dart index 29947d70..181c9482 100644 --- a/lib/models/new_models/assistant_employee.dart +++ b/lib/models/new_models/assistant_employee.dart @@ -1,5 +1,6 @@ import 'package:test_sa/models/base.dart'; import 'package:test_sa/models/new_models/assigned_employee.dart'; + // int? id; // String? userId; // DateTime? startDate; @@ -7,9 +8,9 @@ import 'package:test_sa/models/new_models/assigned_employee.dart'; // int? workingHours; // String? technicalComment; - class AssistantEmployees extends Base { String? userId; + AssistantEmployees({ this.id, this.user, diff --git a/lib/models/new_models/gas_refill_model.dart b/lib/models/new_models/gas_refill_model.dart index 938d94e4..177af0c9 100644 --- a/lib/models/new_models/gas_refill_model.dart +++ b/lib/models/new_models/gas_refill_model.dart @@ -12,37 +12,77 @@ import 'package:test_sa/models/new_models/site.dart'; import 'package:test_sa/models/timer_model.dart'; class GasRefillModel { - GasRefillModel( - {this.id, - this.gazRefillNo, - this.expectedDate, - this.expectedTime, - this.startDate, - this.startTime, - this.endDate, - this.endTime, - this.engSignature, - this.nurseSignature, - this.workingHours, - this.extensionNo, - this.employeeId, - this.name, - this.createdDate, - this.site, - this.building, - this.floor, - this.department, - this.assignedEmployee, - this.status, - this.comment, - this.gazRefillDetails, - this.localEngineerSignature, - this.localNurseSignature, - this.timer}); + GasRefillModel({ + this.id, + this.gasRefillNo, + this.expectedDate, + this.expectedTime, + this.startDate, + this.startTime, + this.endDate, + this.endTime, + this.engSignature, + this.nurseSignature, + this.workingHours, + this.extensionNo, + this.employeeId, + this.name, + this.createdDate, + this.site, + this.building, + this.floor, + this.department, + this.assignedEmployee, + this.status, + this.comment, + this.techComment, + this.gasRefillDetails, + this.localEngineerSignature, + this.localNurseSignature, + this.timer, + this.timerModelList, + this.gasRefillTimers, + this.gasRefillAttachments, + this.statusValue, + }); + + num? id; // Now nullable + String? gasRefillNo; // Now nullable + String? expectedDate; // Now nullable + String? expectedTime; // Now nullable + String? startDate; // Now nullable + String? startTime; // Now nullable + String? endDate; // Now nullable + String? endTime; // Now nullable + String? engSignature; // Now nullable + String? nurseSignature; // Now nullable + double? workingHours; + dynamic extensionNo; + String? employeeId; + String? name; + String? createdDate; + Site? site; // Now nullable + Building? building; // Now nullable + Floor? floor; // Now nullable + Department? department; // Now nullable + AssignedEmployee? assignedEmployee; // Now nullable + Lookup? status; // Now nullable + String? comment; // Now nullable + String? techComment; // Now nullable + List? gasRefillDetails; // Now nullable + Uint8List? localNurseSignature; // Now nullable + Uint8List? localEngineerSignature; // Now nullable + TimerModel? timer = TimerModel(); + + //TODO need to check when api provided.. + List? timerModelList = []; + List? gasRefillTimers = []; + List? gasRefillAttachments; + int? statusValue; GasRefillModel.fromJson(dynamic json) { id = json['id']; - gazRefillNo = json['gazRefillNo']; + gasRefillNo = json['gasRefillNo']; expectedDate = json['expectedDate']; expectedTime = json['expectedTime']; startDate = json['startDate']; @@ -50,28 +90,44 @@ class GasRefillModel { endDate = json['endDate']; endTime = json['endTime']; comment = json['comment']; + techComment = json['techComment']; workingHours = json['workingHours']; extensionNo = json['extensionNo']; employeeId = json['employeeId']; name = json['name']; createdDate = json['createdDate']; - try { - final DateTime? sd = DateTime.tryParse(startDate ?? ""); - final DateTime? st = DateTime.tryParse(startTime ?? ""); - final DateTime? ed = DateTime.tryParse(endDate ?? ""); - final DateTime? et = DateTime.tryParse(endTime ?? ""); - timer = TimerModel( - startAt: st == null ? sd : sd?.add(Duration(hours: st.hour, minutes: st.minute, seconds: st.second)), // Handle potential null 'sd' - endAt: et == null ? ed : ed?.add(Duration(hours: et.hour, minutes: et.minute, seconds: et.second)), // Handle potential null 'ed' - ); - if (timer!.endAt != null && timer!.startAt != null) { - // Use '!' since timer could be null after initialization - timer!.durationInSecond = (timer!.endAt!.difference(timer!.startAt!)).inSeconds; - workingHours = (((timer!.durationInSecond ?? 0) / 60) / 60); - } - } catch (e) { - print(e); + if (json['gasRefillTimers'] != null) { + gasRefillTimers = []; + json['gasRefillTimers'].forEach((v) { + gasRefillTimers?.add(GasRefillTimer.fromJson(v)); + }); + workingHours = json['gasRefillTimers'].fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item['endDate']).difference(DateTime.parse(item['startDate'])).inSeconds) ?? 0; + + } + if (json['gasRefillAttachments'] != null) { + gasRefillAttachments = []; + json['gasRefillAttachments'].forEach((v) { + gasRefillAttachments!.add(GasRefillAttachments.fromJson(v)); + }); } + + // try { + // final DateTime? sd = DateTime.tryParse(startDate ?? ""); + // final DateTime? st = DateTime.tryParse(startTime ?? ""); + // final DateTime? ed = DateTime.tryParse(endDate ?? ""); + // final DateTime? et = DateTime.tryParse(endTime ?? ""); + // timer = TimerModel( + // startAt: st == null ? sd : sd?.add(Duration(hours: st.hour, minutes: st.minute, seconds: st.second)), // Handle potential null 'sd' + // endAt: et == null ? ed : ed?.add(Duration(hours: et.hour, minutes: et.minute, seconds: et.second)), // Handle potential null 'ed' + // ); + // if (timer!.endAt != null && timer!.startAt != null) { + // // Use '!' since timer could be null after initialization + // timer!.durationInSecond = (timer!.endAt!.difference(timer!.startAt!)).inSeconds; + // workingHours = (((timer!.durationInSecond ?? 0) / 60) / 60); + // } + // } catch (e) { + // print(e); + // } engSignature = json['engSignature']; nurseSignature = json['nurseSignature']; site = json['site'] != null ? Site.fromJson(json['site']) : null; @@ -80,129 +136,93 @@ class GasRefillModel { department = json['department'] != null ? Department.fromJson(json['department']) : null; assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null; status = json['status'] != null ? Lookup.fromJson(json['status']) : null; - if (json['gazRefillDetails'] != null) { - gazRefillDetails = []; - json['gazRefillDetails'].forEach((v) { - gazRefillDetails!.add(GasRefillDetails.fromJson(v)); // Use '!' since gazRefillDetails is initialized here + if (json['gasRefillDetails'] != null) { + gasRefillDetails = []; + json['gasRefillDetails'].forEach((v) { + gasRefillDetails!.add(GasRefillDetails.fromJson(v)); // Use '!' since gasRefillDetails is initialized here }); } } - num? id; // Now nullable - String? gazRefillNo; // Now nullable - String? expectedDate; // Now nullable - String? expectedTime; // Now nullable - String? startDate; // Now nullable - String? startTime; // Now nullable - String? endDate; // Now nullable - String? endTime; // Now nullable - String? engSignature; // Now nullable - String? nurseSignature; // Now nullable - num? workingHours; - dynamic extensionNo; - String? employeeId; - String? name; - String? createdDate; - Site? site; // Now nullable - Building? building; // Now nullable - Floor? floor; // Now nullable - Department? department; // Now nullable - AssignedEmployee? assignedEmployee; // Now nullable - Lookup? status; // Now nullable - String? comment; // Now nullable - List? gazRefillDetails; // Now nullable - Uint8List? localNurseSignature; // Now nullable - Uint8List? localEngineerSignature; // Now nullable - TimerModel? timer; // Now nullable - - GasRefillModel copyWith({ - num? id, // Parameters are now nullable - String? gazRefillNo, - String? expectedDate, - String? expectedTime, - String? startDate, - String? startTime, - String? endDate, - String? endTime, - String? engSignature, - String? nurseSignature, - num? workingHours, - num? extensionNo, - num? employeeId, - String? name, - String? createdDate, - Site? site, - Building? building, - Floor? floor, - Department? department, - AssignedEmployee? assignedEmployee, - Lookup? status, - String? comment, - List? gazRefillDetails, - TimerModel? timer, - }) => - GasRefillModel( - id: id ?? this.id, - gazRefillNo: gazRefillNo ?? this.gazRefillNo, - expectedDate: expectedDate ?? this.expectedDate, - expectedTime: expectedTime ?? this.expectedTime, - startDate: startDate ?? this.startDate, - startTime: startTime ?? this.startTime, - endDate: endDate ?? this.endDate, - endTime: endTime ?? this.endTime, - engSignature: engSignature ?? this.engSignature, - nurseSignature: nurseSignature ?? this.nurseSignature, - workingHours: workingHours ?? this.workingHours, - site: site ?? this.site, - building: building ?? this.building, - floor: floor ?? this.floor, - department: department ?? this.department, - assignedEmployee: assignedEmployee ?? this.assignedEmployee, - status: status ?? this.status, - comment: comment ?? this.comment, - gazRefillDetails: gazRefillDetails ?? this.gazRefillDetails, - timer: timer ?? this.timer, - ); - Map toJson() { final map = {}; map['id'] = id ?? 0; - map['gazRefillNo'] = "GR-${DateTime.now().toString().split(" ").first}"; - map['expectedDate'] = expectedDate; - map['expectedTime'] = expectedTime; - map['startDate'] = startDate; - map['startTime'] = startTime; - map['endDate'] = endDate; - map['endTime'] = endTime; - map['engSignature'] = engSignature; - map['nurseSignature'] = nurseSignature; - map['workingHours'] = workingHours; - map['extensionNo'] = extensionNo; - map['employeeId'] = employeeId; - map['name'] = name; - map['createdDate'] = createdDate; - map['comment'] = comment; + map['gasTypeId'] = gasRefillDetails?[0].gasType?.id; + map['cylinderTypeId'] = gasRefillDetails?[0].cylinderType?.id; + map['cylinderSizeId'] = gasRefillDetails?[0].cylinderSize?.id; + map['requestedQty'] = gasRefillDetails?[0].requestedQty; if (site != null) { - map['site'] = site?.toJson(addBuildings: false); // Use '?.' for null safety + map['siteId'] = site?.id; // Use '?.' for null safety } if (building != null) { - map['building'] = building?.toJson(addFloor: false); // Use '?.' for null safety + map['buildingId'] = building?.id; // Use '?.' for null safety } if (floor != null) { - map['floor'] = floor?.toJson(addDepartments: false); // Use '?.' for null safety + map['floorId'] = floor?.id; // Use '?.' for null safety } if (department != null) { - map['department'] = department?.toJson(); // Use '?.' for null safety + map['departmentId'] = department?.id; // Use '?.' for null safety } - if (assignedEmployee != null) { - map['assignedEmployee'] = assignedEmployee?.toJson(); // Use '?.' for null safety + map['comment'] = comment; + + if (gasRefillAttachments != null) { + map['gasRefillAttachments'] = gasRefillAttachments?.map((v) => v.toJson()).toList(); } - if (status != null) { - map['status'] = status?.toJson(); // Use '?.' for null safety + + //older code..... + // map['gasRefillNo'] = "GR-${DateTime.now().toString().split(" ").first}"; + // map['expectedTime'] = expectedTime; + // + // map['startDate'] = startDate; + // map['startTime'] = startTime; + // map['endDate'] = endDate; + // map['endTime'] = endTime; + // map['engSignature'] = engSignature; + // map['nurseSignature'] = nurseSignature; + // map['workingHours'] = workingHours; + // map['extensionNo'] = extensionNo; + // map['employeeId'] = employeeId; + // map['name'] = name; + // map['createdDate'] = createdDate; + // map['comment'] = comment; + // if (site != null) { + // map['site'] = site?.toJson(addBuildings: false); // Use '?.' for null safety + // } + // if (building != null) { + // map['building'] = building?.toJson(addFloor: false); // Use '?.' for null safety + // } + // if (floor != null) { + // map['floor'] = floor?.toJson(addDepartments: false); // Use '?.' for null safety + // } + // if (department != null) { + // map['department'] = department?.toJson(); // Use '?.' for null safety + // } + // if (assignedEmployee != null) { + // map['assignedEmployee'] = assignedEmployee?.toJson(); // Use '?.' for null safety + // } + // if (status != null) { + // map['status'] = status?.toJson(); // Use '?.' for null safety + // } + // if (gasRefillDetails != null) { + // map['gasRefillDetails'] = gasRefillDetails!.map((v) => v.toJson()).toList(); // Use '!' since gasRefillDetails could be null + // } + + return map; + } + + Map toUpdateEngineerPayload({required int status}) { + final map = {}; + map['id'] = id ?? 0; + map['deliveredQty'] = gasRefillDetails?[0].deliverdQty; + map['statusValue'] = status; + map['techComment'] = techComment; + if (gasRefillTimers != null) { + map['gasRefillTimers'] = gasRefillTimers?.map((v) => v.toJson()).toList(); } - if (gazRefillDetails != null) { - map['gazRefillDetails'] = gazRefillDetails!.map((v) => v.toJson()).toList(); // Use '!' since gazRefillDetails could be null + if (gasRefillAttachments != null) { + map['gasRefillAttachments'] = gasRefillAttachments?.map((v) => v.toJson()).toList(); } + return map; } @@ -227,9 +247,9 @@ class GasRefillModel { id = model.id; //userId = model.userId; site = model.site; - gazRefillNo = model.gazRefillNo; + gasRefillNo = model.gasRefillNo; status = Lookup.fromStatus(model.status); - gazRefillDetails = model.gazRefillDetails; + gasRefillDetails = model.gasRefillDetails; building = model.building; floor = model.floor; department = model.department; @@ -246,8 +266,63 @@ class GasRefillModel { extensionNo = model.extensionNo; employeeId = model.employeeId; name = model.name; + techComment = model.techComment; + gasRefillAttachments = model.gasRefillAttachments; createdDate = model.createdDate; + workingHours = model.workingHours; + gasRefillTimers=model.gasRefillTimers; } + + GasRefillModel copyWith({ + num? id, // Parameters are now nullable + String? gasRefillNo, + String? expectedDate, + String? expectedTime, + String? startDate, + String? startTime, + String? endDate, + String? endTime, + String? engSignature, + String? nurseSignature, + double? workingHours, + num? extensionNo, + num? employeeId, + String? name, + String? createdDate, + Site? site, + Building? building, + Floor? floor, + Department? department, + AssignedEmployee? assignedEmployee, + Lookup? status, + String? comment, + List? gasRefillDetails, + List? gasRefillTimer, + TimerModel? timer, + }) => + GasRefillModel( + id: id ?? this.id, + gasRefillNo: gasRefillNo ?? this.gasRefillNo, + expectedDate: expectedDate ?? this.expectedDate, + expectedTime: expectedTime ?? this.expectedTime, + startDate: startDate ?? this.startDate, + startTime: startTime ?? this.startTime, + endDate: endDate ?? this.endDate, + endTime: endTime ?? this.endTime, + engSignature: engSignature ?? this.engSignature, + nurseSignature: nurseSignature ?? this.nurseSignature, + workingHours: workingHours ?? this.workingHours, + site: site ?? this.site, + building: building ?? this.building, + floor: floor ?? this.floor, + department: department ?? this.department, + assignedEmployee: assignedEmployee ?? this.assignedEmployee, + status: status ?? this.status, + comment: comment ?? this.comment, + gasRefillDetails: gasRefillDetails ?? this.gasRefillDetails, + timer: timer ?? this.timer, + gasRefillTimers: gasRefillTimer ?? this.gasRefillTimers, + ); } class GasRefillDetails { @@ -331,3 +406,50 @@ class GasRefillDetails { return true; } } + +class GasRefillTimer { + int? id; + String? startDate; + String? endDate; + dynamic workingHours; + + GasRefillTimer({this.id, this.startDate, this.endDate, this.workingHours}); + + GasRefillTimer.fromJson(Map json) { + id = json['id']; + startDate = json['startDate']; + endDate = json['endDate']; + workingHours = json['workingHours']; + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['startDate'] = startDate; + data['endDate'] = endDate; + data['workingHours'] = workingHours; + return data; + } +} + +class GasRefillAttachments { + int? id; + num? gasRefillId; + String? attachmentName; + + GasRefillAttachments({this.id, this.attachmentName, this.gasRefillId}); + + GasRefillAttachments.fromJson(Map json) { + id = json['id']; + gasRefillId = json['gasRefillId']; + attachmentName = json['attachmentName']; + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['gasRefillId'] = gasRefillId; + data['attachmentName'] = attachmentName; + return data; + } +} diff --git a/lib/models/new_models/work_order_detail_model.dart b/lib/models/new_models/work_order_detail_model.dart index c02bc0a0..25f9af5c 100644 --- a/lib/models/new_models/work_order_detail_model.dart +++ b/lib/models/new_models/work_order_detail_model.dart @@ -84,6 +84,13 @@ class WorkOrderData { required this.totalWorkingHours, this.needAVisitComment, this.needAVisitDateTime, + this.iHaveArrivedDate, + this.rejectReason, + this.closedDate, + this.since, + this.cmFrame, + this.rejectComment, + this.callResponse, required this.workOrderHistory, required this.activities, required this.activityAssetToBeRetireds, @@ -127,9 +134,18 @@ class WorkOrderData { Lookup? failureReasone; FaultDescription? faultDescription; Lookup? solution; + Lookup? cmFrame; + + //cmComments String? totalWorkingHours; DateTime? needAVisitDateTime; String? needAVisitComment; + String? iHaveArrivedDate; + String? closedDate; + Lookup? rejectReason; + String? rejectComment; // need to replace with reject comments. + String? callResponse; // need to replace with reject comments. + int? since; List workOrderHistory; List activities; List activityAssetToBeRetireds; @@ -150,6 +166,13 @@ class WorkOrderData { floor: json["floor"] == null ? null : Lookup.fromJson(json["floor"]), department: json["department"] == null ? null : AssetGroup.fromJson(json["department"]), room: json["room"], + rejectComment: json["rejectComment"], + callResponse: json["callResponse"], + iHaveArrivedDate: json["iHaveArrivedDate"], + closedDate: json["closedDate"], + cmFrame: json["cmFrame"] == null ? null : Lookup.fromJson(json["cmFrame"]), + rejectReason: json["rejectReason"] == null ? null : Lookup.fromJson(json["rejectReason"]), + since: json['since'], assetType: json["assetType"] == null ? null : Lookup.fromJson(json["assetType"]), assignedEmployee: json["assignedEmployee"] == null ? null : WorkOrderAssignedEmployee.fromJson(json["assignedEmployee"]), lastActivityStatus: json["lastActivityStatus"] != null ? Lookup.fromJson(json["lastActivityStatus"]) : null, @@ -174,7 +197,7 @@ class WorkOrderData { failureReasone: json["failureReasone"] == null ? null : Lookup.fromJson(json["failureReasone"]), faultDescription: json["faultDescription"] == null ? null : FaultDescription.fromJson(json["faultDescription"]), solution: json["solution"] == null ? null : Lookup.fromJson(json["solution"]), - totalWorkingHours: (json["totalWorkingHours"] ??"").toString(), + totalWorkingHours: (json["totalWorkingHours"] ?? "").toString(), workOrderHistory: json["workOrderHistory"] == null ? [] : List.from(json["workOrderHistory"]!.map((x) => WorkOrderHistory.fromJson(x))), activities: json["activities"] == null ? [] : List.from(json["activities"]!.map((x) => Activities.fromJson(x))), needAVisitDateTime: DateTime.tryParse(json["needAVisitDateTime"] ?? ""), @@ -281,7 +304,7 @@ class WorkOrderAssignedEmployee { required this.languageId, }); - dynamic userId; + String userId; String? userName; String? email; int? languageId; @@ -357,7 +380,7 @@ class Activities { activityStatus = json['activityStatus'] != null ? Lookup.fromJson(json['activityStatus']) : null; activityMaintenance = json['activityMaintenance'] != null ? ActivityMaintenance.fromJson(json['activityMaintenance']) : null; if (activityMaintenance != null) { - activityType = 'Maintenance Request'; + activityType = 'CM Activity'; } activitySparePart = json['activitySparePart'] != null ? ActivitySparePart.fromJson(json['activitySparePart']) : null; @@ -504,9 +527,9 @@ class WorkOrderContactPerson { String? name; String? employeeId; String? position; - dynamic extension; + String? extension; String? email; - dynamic mobilePhone; + String ?mobilePhone; WorkOrderAssignedEmployee? contactUser; factory WorkOrderContactPerson.fromJson(Map json) { @@ -619,6 +642,7 @@ class ActivityMaintenance { String? supplierStartTime; String? supplierEndTime; double? supplierWorkingHours; + String? activityType; List? assistantEmployees; List? activityMaintenanceTimers; @@ -638,6 +662,7 @@ class ActivityMaintenance { this.supplierEngineer, this.supplierStartTime, this.supplierEndTime, + this.activityType, this.supplierWorkingHours, this.assistantEmployees}); @@ -647,6 +672,7 @@ class ActivityMaintenance { startTime = json['startTime']; endTime = json['endTime']; workingHours = json['workingHours']; + activityType = json['activityType']; travelHours = json['travelHours']; lastSituation = json['lastSituation'] != null ? Lookup.fromJson(json['lastSituation']) : null; repairLocation = json['repairLocation'] != null ? Lookup.fromJson(json['repairLocation']) : null; diff --git a/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart b/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart index 82c9e43d..8d64aa8a 100644 --- a/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart +++ b/lib/models/plan_preventive_visit/plan_preventive_visit_model.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:flutter/widgets.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/models/device/asset.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/service_request/supplier_details.dart'; import 'package:test_sa/models/timer_model.dart'; @@ -24,6 +25,8 @@ class PlanPreventiveVisit { String? departmentName; String? roomName; String? fromDate; + String? creationDate; + String? closedDate; String? toDate; AssignedEmployee? assignedEmployee; DateTime? acutalDateOfVisit; @@ -65,6 +68,8 @@ class PlanPreventiveVisit { this.departmentName, this.roomName, this.fromDate, + this.creationDate, + this.closedDate, this.toDate, this.assignedEmployee, this.acutalDateOfVisit, @@ -105,6 +110,8 @@ class PlanPreventiveVisit { departmentName = json['departmentName']; roomName = json['roomName']; fromDate = json['fromDate']; + creationDate = json['creationDate']; + closedDate = json['closedDate']; toDate = json['toDate']; assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null; acutalDateOfVisit = json['acutalDateOfVisit'] != null ? DateTime.parse(json['acutalDateOfVisit']) : null; @@ -526,27 +533,27 @@ class PlanPreventiveVisit { // } // } -class Asset { - num? id; - String? assetNumber; - String? assetSerialNo; - - Asset({this.id, this.assetNumber, this.assetSerialNo}); - - Asset.fromJson(Map json) { - id = json['id']; - assetNumber = json['assetNumber']; - assetSerialNo = json['assetSerialNo']; - } - - Map toJson() { - final Map data = Map(); - data['id'] = this.id; - data['assetNumber'] = this.assetNumber; - data['assetSerialNo'] = this.assetSerialNo; - return data; - } -} +// class Asset { +// num? id; +// String? assetNumber; +// String? assetSerialNo; +// +// Asset({this.id, this.assetNumber, this.assetSerialNo}); +// +// Asset.fromJson(Map json) { +// id = json['id']; +// assetNumber = json['assetNumber']; +// assetSerialNo = json['assetSerialNo']; +// } +// +// Map toJson() { +// final Map data = Map(); +// data['id'] = this.id; +// data['assetNumber'] = this.assetNumber; +// data['assetSerialNo'] = this.assetSerialNo; +// return data; +// } +// } class AssignedEmployee { String? userId; @@ -776,136 +783,136 @@ class PreventiveVisitSuppliers { } } -class Supplier { - int? id; - String? suppliername; - String? name; - String? website; - String? email; - String? code; - int? suppNo; - String? suppStatusId; - String? cityId; - String? person; - String? comment; - String? zipcode; - String? contact; - List? telephones; - List? faxes; - List? addresses; - List? attachments; - List? suppPersons; - List? suppTCodes; - - Supplier( - {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}); - - Supplier.fromJson(Map json) { - id = json['id']; - 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(v); - }); - } - if (json['faxes'] != null) { - faxes = []; - json['faxes'].forEach((v) { - faxes!.add(v); - }); - } - if (json['addresses'] != null) { - addresses = []; - json['addresses'].forEach((v) { - addresses!.add(v); - }); - } - if (json['attachments'] != null) { - attachments = []; - json['attachments'].forEach((v) { - attachments!.add(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(v); - }); - } - } - - Map toJson() { - final Map data = {}; - data['id'] = id; - data['suppliername'] = suppliername; - data['name'] = name; - data['website'] = website; - data['email'] = email; - data['code'] = code; - data['suppNo'] = suppNo; - data['suppStatusId'] = suppStatusId; - data['cityId'] = cityId; - data['person'] = person; - data['comment'] = comment; - data['zipcode'] = zipcode; - data['contact'] = contact; - if (telephones != null) { - data['telephones'] = telephones!.map((v) => v).toList(); - } - if (faxes != null) { - data['faxes'] = faxes!.map((v) => v).toList(); - } - if (addresses != null) { - data['addresses'] = addresses!.map((v) => v).toList(); - } - if (attachments != null) { - data['attachments'] = attachments!.map((v) => v).toList(); - } - if (suppPersons != null) { - data['suppPersons'] = suppPersons!.map((v) => v.toJson()).toList(); - } - if (suppTCodes != null) { - data['suppTCodes'] = suppTCodes!.map((v) => v).toList(); - } - return data; - } -} +// class Supplier { +// int? id; +// String? suppliername; +// String? name; +// String? website; +// String? email; +// String? code; +// int? suppNo; +// String? suppStatusId; +// String? cityId; +// String? person; +// String? comment; +// String? zipcode; +// String? contact; +// List? telephones; +// List? faxes; +// List? addresses; +// List? attachments; +// List? suppPersons; +// List? suppTCodes; +// +// Supplier( +// {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}); +// +// Supplier.fromJson(Map json) { +// id = json['id']; +// 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(v); +// }); +// } +// if (json['faxes'] != null) { +// faxes = []; +// json['faxes'].forEach((v) { +// faxes!.add(v); +// }); +// } +// if (json['addresses'] != null) { +// addresses = []; +// json['addresses'].forEach((v) { +// addresses!.add(v); +// }); +// } +// if (json['attachments'] != null) { +// attachments = []; +// json['attachments'].forEach((v) { +// attachments!.add(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(v); +// }); +// } +// } +// +// Map toJson() { +// final Map data = {}; +// data['id'] = id; +// data['suppliername'] = suppliername; +// data['name'] = name; +// data['website'] = website; +// data['email'] = email; +// data['code'] = code; +// data['suppNo'] = suppNo; +// data['suppStatusId'] = suppStatusId; +// data['cityId'] = cityId; +// data['person'] = person; +// data['comment'] = comment; +// data['zipcode'] = zipcode; +// data['contact'] = contact; +// if (telephones != null) { +// data['telephones'] = telephones!.map((v) => v).toList(); +// } +// if (faxes != null) { +// data['faxes'] = faxes!.map((v) => v).toList(); +// } +// if (addresses != null) { +// data['addresses'] = addresses!.map((v) => v).toList(); +// } +// if (attachments != null) { +// data['attachments'] = attachments!.map((v) => v).toList(); +// } +// if (suppPersons != null) { +// data['suppPersons'] = suppPersons!.map((v) => v.toJson()).toList(); +// } +// if (suppTCodes != null) { +// data['suppTCodes'] = suppTCodes!.map((v) => v).toList(); +// } +// return data; +// } +// } // class SuppPersons { // int? id; @@ -949,14 +956,14 @@ class PreventiveVisitKits { PreventiveVisitKits.fromJson(Map json) { id = json['id']; + partCatalogItem = json['partCatalogItem'] != null ? PartCatalogItem.fromJson(json['partCatalogItem']) : null; } Map toJson() { - final Map data = Map(); + final Map data = {}; data['id'] = id; if (partCatalogItem != null) { - // data['partCatalogItem'] = partCatalogItem!.toJson(); data['partCatalogItemId'] = partCatalogItem?.id; } return data; diff --git a/lib/models/ppm/recurrent_wo.dart b/lib/models/ppm/recurrent_wo.dart index 4844ce65..8eda557d 100644 --- a/lib/models/ppm/recurrent_wo.dart +++ b/lib/models/ppm/recurrent_wo.dart @@ -53,6 +53,7 @@ class RecurrentWoData { TimerModel? recurrentWoTimerModel = TimerModel(); double? totalWorkingHours = 0.0; List? timerModelList = []; + String? comment; RecurrentWoData( {this.id, @@ -70,6 +71,7 @@ class RecurrentWoData { this.planRecurrentMedicalTaskRooms, this.planRecurrentTaskTimers, this.timerModelList, + this.comment, this.totalWorkingHours}); RecurrentWoData.fromJson(Map json) { @@ -84,6 +86,7 @@ class RecurrentWoData { floor = json["floor"] == null ? null : Lookup.fromJson(json["floor"]); department = json["department"] == null ? null : Lookup.fromJson(json["department"]); room = json["room"] == null ? null : Lookup.fromJson(json["room"]); + comment = json["comment"]; if (json['planRecurrentMedicalTaskRooms'] != null) { planRecurrentMedicalTaskRooms = []; json['planRecurrentMedicalTaskRooms'].forEach((v) { @@ -114,6 +117,7 @@ class RecurrentWoData { } data['id'] = id; data['statusValue'] = status; + data['comment'] = comment; if (planRecurrentTaskTimers != null) { data['planRecurrentTaskTimers'] = planRecurrentTaskTimers!.map((v) => v.toJson()).toList(); @@ -289,7 +293,7 @@ class PlanRecurrentMedicalTaskRoomTabAttributes { PlanRecurrentMedicalTaskRoomTabAttributes.fromJson(Map json) { id = json['id']; attribute = json['attribute'] != null ? Attribute.fromJson(json['attribute']) : null; - attributeValue = json['attributeValue'] ?? (json['attribute']['type'] == 'bool' ? (json['attributeValue']?.toString() == 'true') : json['attributeValue']); + attributeValue = json['attributeValue']; } Map toJson() { diff --git a/lib/models/service_request/spare_parts.dart b/lib/models/service_request/spare_parts.dart index 5571d179..8b4be559 100644 --- a/lib/models/service_request/spare_parts.dart +++ b/lib/models/service_request/spare_parts.dart @@ -5,7 +5,7 @@ class SparePartsWorkOrders extends Base { SparePartsWorkOrders.fromJson(dynamic json) { id = json['id']; - sparePart = json['sparePart'] != null ? SparePart.fromJson(json['sparePart']) : null; + sparePart = json['sparePart'] != null ? SparePart.fromJson(json['sparePart'],true) : null; qty = json['qty']; returnQty = json['returnQty']; @@ -40,35 +40,84 @@ class SparePart extends Base { this.partNo, this.partName, this.oracleCode, + this.displayName, this.assetId, }) : super(identifier: id?.toString(), name: partName); - SparePart.fromJson(dynamic json) { + SparePart.fromJson(dynamic json,bool ?isDisplayName) { id = json['id']; identifier = id?.toString(); partNo = json['partNo']; partName = json['partName']; + displayName = json['displayName']; oracleCode = json['oracleCode']; - name = partName; + name = isDisplayName!=null&&isDisplayName?displayName: partName; assetId = json['assetId']; } num? id; String? partNo; String? partName; + String? displayName; String? oracleCode; num? assetId; - SparePart copyWith({num? id, String? partNo, String? partName, num? assetId,String?oracleCode}) => - SparePart(id: id ?? this.id,oracleCode: oracleCode?? this.oracleCode, partNo: partNo ?? this.partNo, partName: partName ?? this.partName, assetId: assetId ?? this.assetId); + SparePart copyWith({num? id, String? partNo, String? partName, num? assetId,String?oracleCode,String ?displayName}) => + SparePart(id: id ?? this.id,oracleCode: oracleCode?? this.oracleCode, partNo: partNo ?? this.partNo, partName: partName ?? this.partName, assetId: assetId ?? this.assetId,displayName: displayName??this.displayName); Map toJson() { final map = {}; map['id'] = id; map['partNo'] = partNo; map['partName'] = partName; + map['displayName'] = displayName; map['oracleCode'] = oracleCode; map['assetId'] = assetId; return map; } } + +class StoreAvailability { + final int ?id; + final int? storeId; + final int ?availablityQty; + final String? siteName; + final String ?storeName; + final int? requestedQty; + final bool? alreadyRequestFromThisStore; + + StoreAvailability({ + this.id, + this.storeId, + this.availablityQty, + this.siteName, + this.storeName, + this.requestedQty, + this.alreadyRequestFromThisStore, + }); + + factory StoreAvailability.fromJson(Map json) { + return StoreAvailability( + id: json['id'] ?? 0, + storeId: json['storeId'] ?? 0, + availablityQty: json['availablityQty'] ?? 0, + siteName: json['siteName'] ?? '', + storeName: json['storeName'] ?? '', + requestedQty: json['requestedQty'] ?? 0, + alreadyRequestFromThisStore: json['alreadyRequestFromThisStore'] ?? false, + ); + } + + Map toJson() { + return { + 'id': id, + 'storeId': storeId, + 'availablityQty': availablityQty, + 'siteName': siteName, + 'storeName': storeName, + 'requestedQty': requestedQty, + 'alreadyRequestFromThisStore': alreadyRequestFromThisStore, + }; + } +} + diff --git a/lib/new_views/app_style/app_color.dart b/lib/new_views/app_style/app_color.dart index 571e4f06..847b6b59 100644 --- a/lib/new_views/app_style/app_color.dart +++ b/lib/new_views/app_style/app_color.dart @@ -47,6 +47,7 @@ class AppColor { static const Color white60 = Color(0xffEFEFEF); static const Color white70 = Color(0xffF1F1F1); static const Color white80 = Color(0xffF2F4FA); + static const Color white90 = Color(0xffBFD1E4); static const Color white936 = Color(0xff212936); //black @@ -79,6 +80,7 @@ class AppColor { static const Color orange50 = Color(0xffCC9B14); static const Color orange60 = Color(0xff886400); static const Color orange70 = Color(0xffFFC945); + static const Color orange80 = Color(0xff65531B); // static Color greenStatus(BuildContext context) => context.isDark ? const Color(0xff1FA269) : green50; static Color greenStatus(BuildContext context) => context.isDark ? const Color(0xff54C166) : green70.withOpacity(.5); @@ -136,6 +138,27 @@ class AppColor { return Colors.white; } } + static Color getActivityTypeBgColor(String type) { + switch (type) { + case "Internal": + return neutral50; + case "External": + return white90; + default: + + return primary10; + } + } +static Color getActivityTypeTextColor(String type) { + switch (type) { + case "Internal": + return white10; + case "External": + return black10; + default: + return Colors.white; + } + } static Color getHistoryLogStatusColorByName(String status) { switch ((status).toLowerCase()) { diff --git a/lib/new_views/common_widgets/app_filled_button.dart b/lib/new_views/common_widgets/app_filled_button.dart index 153f7431..87376c27 100644 --- a/lib/new_views/common_widgets/app_filled_button.dart +++ b/lib/new_views/common_widgets/app_filled_button.dart @@ -15,6 +15,7 @@ class AppFilledButton extends StatelessWidget { final Color? textColor; final bool showBorder; final double radius; + final int height; final bool disableButton; const AppFilledButton( @@ -25,6 +26,7 @@ class AppFilledButton extends StatelessWidget { this.icon, this.fontSize, this.loading = false, + this.height = 56, this.showBorder = false, this.disableButton = false, this.buttonColor, @@ -36,7 +38,7 @@ class AppFilledButton extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - height: 56.toScreenHeight, + height: height.toScreenHeight, width: maxWidth ? double.infinity : null, alignment: Alignment.center, decoration: BoxDecoration( diff --git a/lib/new_views/common_widgets/app_floating_action_button.dart b/lib/new_views/common_widgets/app_floating_action_button.dart index 29f9892b..bdf4499f 100644 --- a/lib/new_views/common_widgets/app_floating_action_button.dart +++ b/lib/new_views/common_widgets/app_floating_action_button.dart @@ -9,7 +9,7 @@ import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/user.dart'; import 'package:test_sa/new_views/pages/new_gas_refill_request_page.dart'; -import 'package:test_sa/views/pages/device_transfer/request_device_transfer.dart'; +import 'package:test_sa/views/pages/device_transfer/create__asset_transfer_request.dart'; import 'package:test_sa/views/pages/user/requests/create_service_request_page.dart'; import '../app_style/app_color.dart'; @@ -40,7 +40,7 @@ class _AppFloatingActionButtonState extends State { final elements = [ if (user.type == UsersTypes.normal_user) fabItem(context.translation.gasRefillRequest, "gas_refill_request", NewGasRefillRequestPage.routeName), if (user.type == UsersTypes.normal_user) const Divider().defaultStyle(context).paddingOnly(top: 16, bottom: 16), - if (user.type == UsersTypes.normal_user) fabItem(context.translation.transferRequest, "transfer_request", RequestDeviceTransfer.id), + if (user.type == UsersTypes.normal_user) fabItem(context.translation.transferRequest, "transfer_request", CreateAssetTransferRequest.id), if (user.type == UsersTypes.normal_user) const Divider().defaultStyle(context).paddingOnly(top: 16, bottom: 16), if (user.type == UsersTypes.normal_user) fabItem(context.translation.serviceRequest, "service_request", CreateServiceRequestPage.id), ]; diff --git a/lib/new_views/common_widgets/default_app_bar.dart b/lib/new_views/common_widgets/default_app_bar.dart index 6cc8bd5a..faaca183 100644 --- a/lib/new_views/common_widgets/default_app_bar.dart +++ b/lib/new_views/common_widgets/default_app_bar.dart @@ -4,6 +4,7 @@ import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/new_views/pages/land_page/land_page.dart'; +import 'package:test_sa/new_views/swipe_module/dialoge/acknowledge_work_dialog.dart'; import '../app_style/app_color.dart'; @@ -12,8 +13,10 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget { final List? actions; final Function? onBackPress; final bool showHomeActionButton; + final VoidCallback? onWillPopScope; + final TextStyle? titleStyle; - const DefaultAppBar({this.title, this.onBackPress, this.actions, this.showHomeActionButton = false, Key? key}) : super(key: key); + const DefaultAppBar({this.title, this.onBackPress, this.onWillPopScope, this.actions,this.titleStyle, this.showHomeActionButton = false, Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -40,6 +43,18 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget { title: Row( children: [ const Icon(Icons.arrow_back_ios).onPress(() { + if (onWillPopScope != null) { + showDialog( + context: context, + builder: (BuildContext cxt) => AcknowledgeWorkDialog( + onSave: onWillPopScope!, + onDiscard: () { + Navigator.of(cxt).pop(); + }, + ), + ); + return; + } if (onBackPress != null) { onBackPress!(); } else { @@ -49,7 +64,7 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget { 10.width, Text( title ?? "", - style: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + style:titleStyle?? AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ).expanded, ], ), diff --git a/lib/new_views/pages/land_page/create_request-type_bottomsheet.dart b/lib/new_views/pages/land_page/create_request-type_bottomsheet.dart index 6c405780..e26ca02b 100644 --- a/lib/new_views/pages/land_page/create_request-type_bottomsheet.dart +++ b/lib/new_views/pages/land_page/create_request-type_bottomsheet.dart @@ -8,6 +8,7 @@ import 'package:test_sa/new_views/pages/new_gas_refill_request_page.dart'; import 'package:test_sa/service_request_latest/views/nurse/create_new_request_view.dart'; import 'package:test_sa/views/pages/device_transfer/request_device_transfer.dart'; import 'package:test_sa/views/pages/user/tasks_request/create_task_view.dart'; +import 'package:test_sa/views/pages/device_transfer/create__asset_transfer_request.dart'; class CreateRequestTypeBottomSheet extends StatelessWidget { final bool isEngineer; @@ -65,7 +66,7 @@ class CreateRequestTypeBottomSheet extends StatelessWidget { icon: 'add_icon', label: context.translation.deviceTransfer, onTap: () async { - Navigator.pushReplacementNamed(context, RequestDeviceTransfer.id); + Navigator.pushReplacementNamed(context, CreateAssetTransferRequest.id); }, ), listCard( diff --git a/lib/new_views/pages/land_page/my_request/all_requests_filter_page.dart b/lib/new_views/pages/land_page/my_request/all_requests_filter_page.dart index 0ce17697..ac7c3b92 100644 --- a/lib/new_views/pages/land_page/my_request/all_requests_filter_page.dart +++ b/lib/new_views/pages/land_page/my_request/all_requests_filter_page.dart @@ -1,9 +1,11 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/search_all_requests_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; @@ -43,6 +45,7 @@ class _AllRequestsFilterPageState extends State { @override Widget build(BuildContext context) { + bool isEngineer = (Provider.of(context, listen: false).user?.type) == UsersTypes.engineer; if (search == null) { search = SearchAllRequestsModel( requestNumber: SearchByRequestNumberModel(context, controller: TextEditingController()), @@ -59,14 +62,17 @@ class _AllRequestsFilterPageState extends State { context.translation.gasRefill: 2, context.translation.deviceTransfer: 3, context.translation.preventiveMaintenance: 4, - context.translation.recurrentWo: 5, }; + if (isEngineer) { + types.addAll({context.translation.recurrentWo: 5}); + } final statuses = { - context.translation.allRequests: 0, + "All WO": 0, context.translation.open: 1, context.translation.inProgress: 2, context.translation.completed: 4, context.translation.closed: 3, + "Canceled": 5, }; return Scaffold( appBar: DefaultAppBar( @@ -99,7 +105,7 @@ class _AllRequestsFilterPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - context.translation.requestStatus.heading5(context), + "WO Status".heading5(context), 8.height, RequestsTypeFilter( initialValues: search?.statuses ?? [], @@ -116,7 +122,7 @@ class _AllRequestsFilterPageState extends State { }, ), 16.height, - context.translation.typeOfRequest.heading5(context), + "Type of WO".heading5(context), 8.height, RequestsTypeFilter( initialValues: search?.typeTransaction ?? [], @@ -155,25 +161,25 @@ class _AllRequestsFilterPageState extends State { ], ), 16.height, - "Archived Requests".heading5(context), - // 8.height, - Row( - children: [ - Checkbox( - value: search?.isArchived ?? false, - activeColor: AppColor.blueStatus(context), - onChanged: (value) { - if (search?.isArchived != value) { - search?.isArchived = value!; - } - if (mounted) setState(() {}); - }), - "View Archived Requests".bodyText(context).expanded, - ], - ).onPress(() { - search?.isArchived = !search!.isArchived; - setState(() {}); - }), + // "Archived WO".heading5(context), + // // 8.height, + // Row( + // children: [ + // Checkbox( + // value: search?.isArchived ?? false, + // activeColor: AppColor.blueStatus(context), + // onChanged: (value) { + // if (search?.isArchived != value) { + // search?.isArchived = value!; + // } + // if (mounted) setState(() {}); + // }), + // "View Archived Requests".bodyText(context).expanded, + // ], + // ).onPress(() { + // search?.isArchived = !search!.isArchived; + // setState(() {}); + // }), ], ).paddingOnly(start: 16, end: 16), ).expanded, diff --git a/lib/new_views/pages/land_page/requests/gas_refill_item_view.dart b/lib/new_views/pages/land_page/requests/gas_refill_item_view.dart index a817e22f..00f848f6 100644 --- a/lib/new_views/pages/land_page/requests/gas_refill_item_view.dart +++ b/lib/new_views/pages/land_page/requests/gas_refill_item_view.dart @@ -21,7 +21,9 @@ class GasRefillItemView extends StatelessWidget { @override Widget build(BuildContext context) { + if (requestData != null) { + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/new_views/pages/land_page/requests/ppm_item_view.dart b/lib/new_views/pages/land_page/requests/ppm_item_view.dart index a4569881..100f47de 100644 --- a/lib/new_views/pages/land_page/requests/ppm_item_view.dart +++ b/lib/new_views/pages/land_page/requests/ppm_item_view.dart @@ -49,10 +49,11 @@ class PpmItemView extends StatelessWidget { 8.height, (requestData?.typeTransaction ?? context.translation.ppmRequest).heading5(context), 8.height, + '${context.translation.assetName}: ${requestData!.assetName}'.bodyText(context), '${context.translation.assetNumber}: ${requestData!.assetNumber}'.bodyText(context), // '${context.translation.assetSN}: ${request.assetSN}'.bodyText(context),//todo ask ahmed // '${context.translation.code}: ${request.code}'.bodyText(context), - '${context.translation.requestNo}: ${requestData!.requestNo}'.bodyText(context), + 'PM No: ${requestData!.requestNo}'.bodyText(context), 16.height, Row( mainAxisSize: MainAxisSize.min, @@ -99,10 +100,11 @@ class PpmItemView extends StatelessWidget { 8.height, (requestDetails?.nameOfType ?? context.translation.ppmRequest).heading5(context), 8.height, + '${context.translation.assetName}: ${requestDetails!.assetName}'.bodyText(context), '${context.translation.assetNumber}: ${requestDetails!.assetNo}'.bodyText(context), '${context.translation.assetSN}: ${requestDetails!.assetSN}'.bodyText(context), // '${context.translation.code}: ${request.code}'.bodyText(context), - '${context.translation.requestNo}: ${requestDetails!.requestNo}'.bodyText(context), + 'PM No: ${requestDetails!.requestNo}'.bodyText(context), 16.height, Row( mainAxisSize: MainAxisSize.min, diff --git a/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart b/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart index ec9223f3..1387d6dc 100644 --- a/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart +++ b/lib/new_views/pages/land_page/requests/recurrent_wo_item_view.dart @@ -52,7 +52,7 @@ class RecurrentWoItemView extends StatelessWidget { // '${context.translation.assetNumber}: ${requestData!.assetNumber}'.bodyText(context), // '${context.translation.assetSN}: ${request.assetSN}'.bodyText(context),//todo ask ahmed // '${context.translation.code}: ${request.code}'.bodyText(context), - '${context.translation.requestNo}: ${requestData!.requestNo}'.bodyText(context), + '${context.translation.taskNo}: ${requestData!.requestNo}'.bodyText(context), 16.height, Row( mainAxisSize: MainAxisSize.min, @@ -102,7 +102,7 @@ class RecurrentWoItemView extends StatelessWidget { // '${context.translation.taskNo}: ${requestDetails!.id}'.bodyText(context), '${context.translation.site}: ${requestDetails!.site}'.bodyText(context), // '${context.translation.code}: ${request.code}'.bodyText(context), - '${context.translation.requestNo}: ${requestDetails!.requestNo}'.bodyText(context), + '${context.translation.taskNo}: ${requestDetails!.requestNo}'.bodyText(context), 16.height, Row( mainAxisSize: MainAxisSize.min, diff --git a/lib/new_views/pages/land_page/requests/service_request_item_view.dart b/lib/new_views/pages/land_page/requests/service_request_item_view.dart index e9b09bbc..e3fabae7 100644 --- a/lib/new_views/pages/land_page/requests/service_request_item_view.dart +++ b/lib/new_views/pages/land_page/requests/service_request_item_view.dart @@ -52,12 +52,14 @@ class ServiceRequestItemView extends StatelessWidget { 8.height, (requestData?.typeTransaction ?? context.translation.correctiveMaintenance).heading5(context), 8.height, - '${context.translation.assetName}: ${requestData!.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), + 'CM Number: ${requestData!.requestNo}'.bodyText(context), + '${context.translation.assetNumber}: ${requestData?.assetNumber}'.bodyText(context), + '${context.translation.assetName}: ${requestData?.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), // '${context.translation.assetNumber}: ${request.assetNo}'.bodyText(context), // '${context.translation.requestType}: ${requestData!.requestTypeName}'.bodyText(context), - '${context.translation.requestNo}: ${requestData!.requestNo}'.bodyText(context), + if (requestData?.statusName == 'Canceled') ...[ - '${context.translation.rejectionReason}: ${requestData!.rejectReason}'.bodyText(context), + '${context.translation.rejectionReason}: ${requestData?.rejectReason}'.bodyText(context), ], 8.height, Row( @@ -110,10 +112,11 @@ class ServiceRequestItemView extends StatelessWidget { 8.height, (requestDetails!.nameOfType ?? context.translation.correctiveMaintenance).heading5(context), 8.height, - '${context.translation.assetName}: ${requestDetails!.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), + + // '${context.translation.requestType}: ${requestDetails!.requestType}'.bodyText(context), + 'CM Number: ${requestDetails!.requestNo}'.bodyText(context), '${context.translation.assetNumber}: ${requestDetails!.assetNo}'.bodyText(context), - '${context.translation.requestType}: ${requestDetails!.requestType}'.bodyText(context), - '${context.translation.requestNo}: ${requestDetails!.requestNo}'.bodyText(context), + '${context.translation.assetName}: ${requestDetails!.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), 8.height, Row( // mainAxisSize: MainAxisSize.min, diff --git a/lib/new_views/pages/new_gas_refill_request_page.dart b/lib/new_views/pages/new_gas_refill_request_page.dart index 162afa91..e1fb13cf 100644 --- a/lib/new_views/pages/new_gas_refill_request_page.dart +++ b/lib/new_views/pages/new_gas_refill_request_page.dart @@ -1,7 +1,10 @@ +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/user_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; @@ -14,12 +17,17 @@ import 'package:test_sa/models/new_models/gas_refill_model.dart'; import 'package:test_sa/models/new_models/site.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart'; import 'package:test_sa/providers/gas_request_providers/cylinder_size_provider.dart'; import 'package:test_sa/providers/gas_request_providers/cylinder_type_provider.dart'; import 'package:test_sa/providers/gas_request_providers/gas_types_provider.dart'; import 'package:test_sa/providers/gas_request_providers/site_provider.dart'; import 'package:test_sa/providers/loading_list_notifier.dart'; +import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; +import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart'; +import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; + import '../../controllers/providers/api/gas_refill_provider.dart'; import '../common_widgets/default_app_bar.dart'; @@ -36,6 +44,9 @@ class _NewGasRefillRequestPageState extends State { late GasRefillDetails _currentDetails; late GasRefillModel _gasModel; Lookup? _requestedQuantity; + final TextEditingController _commentController = TextEditingController(); + GasRefillProvider? _gasRefillProvider; + List _files = []; static List gasQuantity = [ Lookup(name: "1", id: 1, value: 1), @@ -48,8 +59,10 @@ class _NewGasRefillRequestPageState extends State { @override void initState() { super.initState(); + _gasRefillProvider ??= Provider.of(context, listen: false); + _gasModel =GasRefillModel(); _currentDetails = GasRefillDetails(); - _gasModel = GasRefillModel(gazRefillDetails: []); + _gasModel = GasRefillModel(gasRefillDetails: []); } @override @@ -59,39 +72,33 @@ class _NewGasRefillRequestPageState extends State { @override Widget build(BuildContext context) { + return Scaffold( appBar: DefaultAppBar(title: context.translation.newGasRefillRequest), body: Column( children: [ + 12.height, SingleChildScrollView( child: Column( children: [ - 16.height, SingleItemDropDownMenu( context: context, title: context.translation.gasType, initialValue: _currentDetails.gasType, + backgroundColor: AppColor.neutral100, + showShadow: false, showAsBottomSheet: true, onSelect: (value) { _currentDetails.gasType = value; }, ), 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.quantity, - initialValue: _requestedQuantity, - staticData: gasQuantity, - onSelect: (value) { - _requestedQuantity = value; - _currentDetails.requestedQty = value?.value; - }, - ), - 8.height, SingleItemDropDownMenu( context: context, title: context.translation.cylinderType, initialValue: _currentDetails.cylinderType, + backgroundColor: AppColor.neutral100, + showShadow: false, onSelect: (value) { _currentDetails.cylinderType = value; }, @@ -102,136 +109,153 @@ class _NewGasRefillRequestPageState extends State { title: context.translation.cylinderSize, initialValue: _currentDetails.cylinderSize, showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, onSelect: (value) { _currentDetails.cylinderSize = value; }, ), 8.height, - SingleItemDropDownMenu( + SingleItemDropDownMenu( context: context, - title: context.translation.site, - initialValue: _gasModel.site, + title: context.translation.quantity, showAsBottomSheet: true, + initialValue: _requestedQuantity, + staticData: gasQuantity, + backgroundColor: AppColor.neutral100, + showShadow: false, onSelect: (value) { - setState(() { - _gasModel.site = value; - _gasModel.building = null; - _gasModel.floor = null; - _gasModel.department = null; - }); + _requestedQuantity = value; + _currentDetails.requestedQty = value?.value; }, ), 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.building, - initialValue: _gasModel.building, - enabled: _gasModel.site?.buildings?.isNotEmpty ?? false, - staticData: _gasModel.site?.buildings ?? [], - showAsBottomSheet: true, - onSelect: (value) { - setState(() { - _gasModel.building = value; - _gasModel.floor = null; - _gasModel.department = null; - }); - }, + Row( + children: [ + SingleItemDropDownMenu( + context: context, + title: context.translation.site, + initialValue: _gasModel.site, + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + onSelect: (value) { + setState(() { + _gasModel.site = value; + _gasModel.building = null; + _gasModel.floor = null; + _gasModel.department = null; + }); + }, + ).expanded, + 8.width, + SingleItemDropDownMenu( + context: context, + title: context.translation.building, + initialValue: _gasModel.building, + enabled: _gasModel.site?.buildings?.isNotEmpty ?? false, + staticData: _gasModel.site?.buildings ?? [], + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + onSelect: (value) { + setState(() { + _gasModel.building = value; + _gasModel.floor = null; + _gasModel.department = null; + }); + }, + ).expanded, + ], ), 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.floor, - initialValue: _gasModel.floor, - enabled: _gasModel.building?.floors?.isNotEmpty ?? false, - staticData: _gasModel.building?.floors ?? [], - showAsBottomSheet: true, - onSelect: (value) { - setState(() { - _gasModel.floor = value; - _gasModel.department = null; - }); - }, + Row( + children: [ + SingleItemDropDownMenu( + context: context, + title: context.translation.floor, + initialValue: _gasModel.floor, + enabled: _gasModel.building?.floors?.isNotEmpty ?? false, + staticData: _gasModel.building?.floors ?? [], + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + onSelect: (value) { + setState(() { + _gasModel.floor = value; + _gasModel.department = null; + }); + }, + ).expanded, + 8.width, + SingleItemDropDownMenu( + context: context, + title: context.translation.department, + initialValue: _gasModel.department, + enabled: _gasModel.floor?.departments?.isNotEmpty ?? false, + staticData: _gasModel.floor?.departments ?? [], + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + onSelect: (value) { + _gasModel.department = value; + }, + ).expanded, + ], ), 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.department, - initialValue: _gasModel.department, - enabled: _gasModel.floor?.departments?.isNotEmpty ?? false, - staticData: _gasModel.floor?.departments ?? [], - showAsBottomSheet: true, - onSelect: (value) { - _gasModel.department = value; + AppTextFormField( + labelText: context.translation.callComments, + labelStyle: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral120), + textInputType: TextInputType.multiline, + alignLabelWithHint: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + controller: _commentController, + onChange: (value){ + _gasModel.comment = value; }, + onSaved: (value) {}, ), 8.height, - if (_gasModel.gazRefillDetails?.isEmpty ?? true) - AppFilledButton( - label: context.translation.add, - maxWidth: true, - textColor: Colors.white, - buttonColor: context.isDark ? AppColor.neutral60 : AppColor.neutral50, - onPressed: _add, - ), - ListView.builder( - shrinkWrap: true, - itemCount: _gasModel.gazRefillDetails?.length, - padding: const EdgeInsets.only(top: 12, bottom: 24), - physics: const NeverScrollableScrollPhysics(), - itemBuilder: (context, index) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - (_gasModel.gazRefillDetails![index].gasType?.name ?? "").heading5(context), - 8.height, - ("${context.translation.quantity}: ${_gasModel.gazRefillDetails![index].requestedQty}").bodyText(context), - ("${context.translation.cylinderSize}: ${_gasModel.gazRefillDetails![index].cylinderSize?.name}").bodyText(context), - ("${context.translation.cylinderType}: ${_gasModel.gazRefillDetails![index].cylinderType?.name}").bodyText(context), - ], - ), - Container( - height: 48.toScreenWidth, - width: 48.toScreenWidth, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(100), - border: Border.all(color: context.isDark ? AppColor.neutral50 : AppColor.neutral30), - ), - padding: EdgeInsets.symmetric(vertical: 12.toScreenHeight), - child: "trash".toSvgAsset(fit: BoxFit.fitHeight, color: context.isDark ? AppColor.red40 : AppColor.red50), - ).onPress(() { - _delete(index); - }), - ], - ), - const Divider().defaultStyle(context), - ("${context.translation.site}: ${_gasModel.site?.custName}").bodyText(context), - ("${context.translation.building}: ${_gasModel.building?.name}").bodyText(context), - ("${context.translation.floor}: ${_gasModel.floor?.name}").bodyText(context), - ("${context.translation.department}: ${_gasModel.department?.departmentName}").bodyText(context), - ], - ).toShadowContainer(context); - }, + MultiFilesPicker( + label: context.translation.attachFiles, + files:_files, + buttonColor: AppColor.black10, + onlyImages: false, + buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), ), ], - ), + ).toShadowContainer(context, padding: 10).paddingOnly(start: 16, end: 16, top: 16), ).expanded, 16.height, - AppFilledButton(label: context.translation.submitRequest, maxWidth: true, onPressed: _submit), + FooterActionButton.footerContainer(child: AppFilledButton(label: context.translation.submitRequest, maxWidth: true, onPressed: _submit)), ], - ).paddingOnly(start: 16, end: 16, bottom: 24), + ), + ); + } + + Future _submit() async { + if (_currentDetails.gasType==null) { + Fluttertoast.showToast(msg: context.translation.youHaveToAddRequests); + return; + } + _gasModel.gasRefillDetails=[]; + _gasModel.gasRefillDetails?.add(_currentDetails); + _gasModel.gasRefillAttachments = []; + for (var item in _files) { + _gasModel.gasRefillAttachments?.add(GasRefillAttachments( + id: 0, gasRefillId: _gasModel.id ?? 0, attachmentName: ServiceRequestUtils.isLocalUrl(item.path) ? "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}" : item.path)); + } + await _gasRefillProvider?.addGasRefillRequest( + context: context, + model: _gasModel, ); } void _add() async { if (_currentDetails.validate(context) && _gasModel.validate(context)) { - _gasModel.gazRefillDetails!.add(_currentDetails); + _gasModel.gasRefillDetails!.add(_currentDetails); _currentDetails = GasRefillDetails(); _requestedQuantity = null; setState(() {}); @@ -239,19 +263,62 @@ class _NewGasRefillRequestPageState extends State { } void _delete(index) { - _gasModel.gazRefillDetails!.remove(_gasModel.gazRefillDetails![index]); + _gasModel.gasRefillDetails!.remove(_gasModel.gasRefillDetails![index]); setState(() {}); } - - Future _submit() async { - if (_gasModel.gazRefillDetails?.isEmpty ?? true) { - Fluttertoast.showToast(msg: context.translation.youHaveToAddRequests); - return; - } - await Provider.of(context, listen: false).createModel( - context: context, - user: Provider.of(context, listen: false).user!, - model: _gasModel, - ); - } +//older code.... +// if (_gasModel.gasRefillDetails?.isEmpty ?? true) +// AppFilledButton( +// label: context.translation.add, +// maxWidth: true, +// textColor: Colors.white, +// buttonColor: context.isDark ? AppColor.neutral60 : AppColor.neutral50, +// onPressed: _add, +// ), +// ListView.builder( +// shrinkWrap: true, +// itemCount: _gasModel.gasRefillDetails?.length, +// padding: const EdgeInsets.only(top: 12, bottom: 24), +// physics: const NeverScrollableScrollPhysics(), +// itemBuilder: (context, index) { +// return Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// (_gasModel.gasRefillDetails![index].gasType?.name ?? "").heading5(context), +// 8.height, +// ("${context.translation.quantity}: ${_gasModel.gasRefillDetails![index].requestedQty}").bodyText(context), +// ("${context.translation.cylinderSize}: ${_gasModel.gasRefillDetails![index].cylinderSize?.name}").bodyText(context), +// ("${context.translation.cylinderType}: ${_gasModel.gasRefillDetails![index].cylinderType?.name}").bodyText(context), +// ], +// ), +// Container( +// height: 48.toScreenWidth, +// width: 48.toScreenWidth, +// decoration: BoxDecoration( +// borderRadius: BorderRadius.circular(100), +// border: Border.all(color: context.isDark ? AppColor.neutral50 : AppColor.neutral30), +// ), +// padding: EdgeInsets.symmetric(vertical: 12.toScreenHeight), +// child: "trash".toSvgAsset(fit: BoxFit.fitHeight, color: context.isDark ? AppColor.red40 : AppColor.red50), +// ).onPress(() { +// _delete(index); +// }), +// ], +// ), +// const Divider().defaultStyle(context), +// ("${context.translation.site}: ${_gasModel.site?.custName}").bodyText(context), +// ("${context.translation.building}: ${_gasModel.building?.name}").bodyText(context), +// ("${context.translation.floor}: ${_gasModel.floor?.name}").bodyText(context), +// ("${context.translation.department}: ${_gasModel.department?.departmentName}").bodyText(context), +// ], +// ).toShadowContainer(context); +// }, +// ), } diff --git a/lib/new_views/swipe_module/dialoge/acknowledge_work_dialog.dart b/lib/new_views/swipe_module/dialoge/acknowledge_work_dialog.dart new file mode 100644 index 00000000..81ee9a1d --- /dev/null +++ b/lib/new_views/swipe_module/dialoge/acknowledge_work_dialog.dart @@ -0,0 +1,67 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; + +class AcknowledgeWorkDialog extends StatelessWidget { + final String? title; + final String? message; + final String? okTitle; + final VoidCallback onSave; + final VoidCallback onDiscard; + + const AcknowledgeWorkDialog( + {Key? key, this.title, this.message = "To prevent the risk of losing your changes, Please confirm Save or Discard", this.okTitle, required this.onSave, required this.onDiscard}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Dialog( + backgroundColor: Colors.white, + shape: const RoundedRectangleBorder(), + insetPadding: const EdgeInsets.only(left: 21, right: 21), + child: Padding( + padding: const EdgeInsets.only(left: 20, right: 20, top: 18, bottom: 28), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + const Text( + "Confirm", + style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600, color: Colors.black87, height: 35 / 24, letterSpacing: -0.96), + ).paddingOnly(top: 16, bottom: 8), + message != null ? message!.heading5(context).custom(color: AppColor.neutral50) : const SizedBox(), + 28.height, + Row( + children: [ + AppFilledButton( + label: "Discard", + buttonColor: Colors.white54, + textColor: AppColor.red30, + height: 40, + showBorder: true, + onPressed: () { + Navigator.of(context).pop(); + onDiscard(); + }, + ).expanded, + 16.width, + AppFilledButton( + label: "Save", + onPressed: () { + Navigator.of(context).pop(); + onSave(); + }, + height: 40, + buttonColor: AppColor.green70, + ).expanded, + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/new_views/swipe_module/dialoge/confirm_dialog.dart b/lib/new_views/swipe_module/dialoge/confirm_dialog.dart index 3e07310f..f8cfacfb 100644 --- a/lib/new_views/swipe_module/dialoge/confirm_dialog.dart +++ b/lib/new_views/swipe_module/dialoge/confirm_dialog.dart @@ -6,13 +6,13 @@ import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; class ConfirmDialog extends StatelessWidget { - final String ?title; - final String ?message; - final String ?okTitle; - final VoidCallback ?onTap; - final VoidCallback ?onCloseTap; + final String? title; + final String? message; + final String? okTitle; + final VoidCallback? onTap; + final VoidCallback? onCloseTap; - const ConfirmDialog({Key ?key, this.title, this.message, this.okTitle, this.onTap, this.onCloseTap}) : super(key: key); + const ConfirmDialog({Key? key, this.title, this.message, this.okTitle, this.onTap, this.onCloseTap}) : super(key: key); @override Widget build(BuildContext context) { @@ -45,7 +45,7 @@ class ConfirmDialog extends StatelessWidget { ) ], ), - message!=null?message!.heading5(context).custom(color: AppColor.neutral70):const SizedBox(), + message != null ? message!.heading5(context).custom(color: AppColor.neutral70) : const SizedBox(), 28.height, AppFilledButton( label: okTitle ?? "OK", diff --git a/lib/service_request_latest/service_request_detail_provider.dart b/lib/service_request_latest/service_request_detail_provider.dart index ffaca293..2902002b 100644 --- a/lib/service_request_latest/service_request_detail_provider.dart +++ b/lib/service_request_latest/service_request_detail_provider.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:developer'; +import 'dart:io'; import 'package:flutter/material.dart'; import 'package:http/src/response.dart'; @@ -13,7 +14,9 @@ import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_mo import 'package:test_sa/models/new_models/arrival_verification_type_model.dart'; import 'package:test_sa/models/new_models/dashboard_detail.dart'; import 'package:test_sa/models/new_models/work_order_detail_model.dart'; +import 'package:test_sa/models/service_request/spare_parts.dart'; import 'package:test_sa/models/service_request/supplier_details.dart'; +import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; class ServiceRequestDetailProvider extends ChangeNotifier { final pageItemNumber = 10; @@ -102,6 +105,15 @@ class ServiceRequestDetailProvider extends ChangeNotifier { AssetRetiredHelperModel? assetRetiredHelperModel = AssetRetiredHelperModel(); ActivityMaintenanceHelperModel? activityMaintenanceHelperModel = ActivityMaintenanceHelperModel(); SparePartHelperModel? sparePartHelperModel; + List _storeAvailability= []; + + List get storeAvailability => _storeAvailability; + + set storeAvailability(List value) { + _storeAvailability = value; + notifyListeners(); + } + FixRemotelyHelperModel? fixRemotelyHelperModel = FixRemotelyHelperModel(); NeedVisitHelperModel? needVisitHelperModel = NeedVisitHelperModel(); NurseActionHelperModel? nurseActionHelperModel; @@ -183,7 +195,15 @@ class ServiceRequestDetailProvider extends ChangeNotifier { notifyListeners(); } - //create workOrder nurse ..... + bool _isReadOnlyRequest = false; + + bool get isReadOnlyRequest => _isReadOnlyRequest; + + set isReadOnlyRequest(bool value) { + _isReadOnlyRequest = value; + notifyListeners(); + } //create workOrder nurse ..... + Future createWorkOrder() async { isLoading = true; notifyListeners(); @@ -213,6 +233,39 @@ class ServiceRequestDetailProvider extends ChangeNotifier { notifyListeners(); final response = await ApiManager.instance.get(URLs.getWorkOrderByIdUrl + "?workOrderId=$id"); stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body)); + //need to check on value as id changed on different env. + if (currentWorkOrder?.data?.status?.value == 3 || currentWorkOrder?.data?.status?.value == 5 || currentWorkOrder?.data?.status?.value == 6) { + isReadOnlyRequest = true; + } else { + isReadOnlyRequest = false; + } + } + isLoading = false; + notifyListeners(); + } catch (e) { + log("getWorkOrder [error] : $e"); + isLoading = false; + notifyListeners(); + return null; + } + } + + + //upload workorder attachment by engineer.. + Future addWorkOrderAttachment({required int woId, required List attachments}) async { + try { + List woAttachments = []; + for (var file in attachments) { + String fileName = ServiceRequestUtils.isLocalUrl(file.path) ? ("${file.path.split("/").last}|${base64Encode(File(file.path).readAsBytesSync())}") : file.path; + woAttachments.add(WorkOrderAttachments(id: 0, name: fileName)); + } + + isLoading = true; + notifyListeners(); + final response = await ApiManager.instance.post(URLs.uploadWorkOrderAttachmentsUrl, body: WorkOrderHelperModel().toUploadAttachmentJson(woId, woAttachments)); + stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body)); } @@ -700,6 +753,33 @@ class ServiceRequestDetailProvider extends ChangeNotifier { } } + Future getStoreAvailabilityById({required num? partId}) async { + try { + isLoading = true; + notifyListeners(); + + final response = await ApiManager.instance.post( + URLs.getSparePartAvailableQuantity + "?PartId=$partId", + body: {}, + ); + + print('response i got is ${response.body}'); + stateCode = response.statusCode; + + if (response.statusCode >= 200 && response.statusCode < 300) { + final List data = json.decode(response.body)["data"]; + storeAvailability = data.map((item) => StoreAvailability.fromJson(item)).toList(); + } + + isLoading = false; + notifyListeners(); + } catch (e) { + log("getStoreAvalivility [error] : $e"); + isLoading = false; + notifyListeners(); + } + } + Future deleteActivitySparePart({required int id, required int workOrderId}) async { isLoading = true; notifyListeners(); diff --git a/lib/service_request_latest/utilities/service_request_utils.dart b/lib/service_request_latest/utilities/service_request_utils.dart index b18f5ee8..9deccbfa 100644 --- a/lib/service_request_latest/utilities/service_request_utils.dart +++ b/lib/service_request_latest/utilities/service_request_utils.dart @@ -457,7 +457,6 @@ class ConfirmArrivalNotificationModel { this.accept, }); - // Factory constructor to create an instance from a Map (e.g., JSON) factory ConfirmArrivalNotificationModel.fromJson(Map json) { return ConfirmArrivalNotificationModel( transactionType: json['transactionType'], diff --git a/lib/service_request_latest/views/components/action_button/footer_action_button.dart b/lib/service_request_latest/views/components/action_button/footer_action_button.dart index 789fe025..4fbbf7bc 100644 --- a/lib/service_request_latest/views/components/action_button/footer_action_button.dart +++ b/lib/service_request_latest/views/components/action_button/footer_action_button.dart @@ -8,6 +8,7 @@ import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/enums/work_order_next_step.dart'; import 'package:test_sa/models/helper_data_models/workorder/work_order_helper_models.dart'; +import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/new_models/work_order_detail_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; @@ -34,10 +35,10 @@ class FooterActionButton { {required WorkOrderNextStepEnum workOrderNextStepStatus, List activities = const [], required BuildContext context, + Lookup? status, required UserProvider userProvider, bool isEmpIsAssigned = false}) { ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); - bool showMarkAsFixedButton = activities.isEmpty ? false : activities.any((object) => object.activityStatus!.value == 14 || object.activityStatus!.value == 19); if (userProvider.user?.type == UsersTypes.engineer) { if (workOrderNextStepStatus == WorkOrderNextStepEnum.assignToMe && isEmpIsAssigned) return const SizedBox(); @@ -56,8 +57,39 @@ class FooterActionButton { case WorkOrderNextStepEnum.markedAsFixed: break; // TODO: Handle this case. + case WorkOrderNextStepEnum.endWorkFlow: + if (requestDetailProvider.isReadOnlyRequest) { + return footerContainer( + child: AppFilledButton( + label: context.translation.activities, + buttonColor: AppColor.neutral50, + onPressed: () async { + Navigator.push(context, MaterialPageRoute(builder: (context) => const ActivitiesListView())); + }, + ), + ); + } + return footerContainer( + child: AppFilledButton( + label: context.translation.close, + // maxWidth: true, + buttonColor: AppColor.primary10, + onPressed: () async { + Navigator.pop(context); + }, + )); case WorkOrderNextStepEnum.nTakeAction: - // const SizedBox().flushBar(context: context, title: context.translation.youMarkedThisIssueAsFixedWaitingForTheRequesterToConfirm, message: ''); + if (requestDetailProvider.isReadOnlyRequest) { + return footerContainer( + child: AppFilledButton( + label: context.translation.activities, + buttonColor: AppColor.neutral50, + onPressed: () async { + Navigator.push(context, MaterialPageRoute(builder: (context) => const ActivitiesListView())); + }, + ), + ); + } return footerContainer( child: AppFilledButton( label: context.translation.close, diff --git a/lib/service_request_latest/views/components/activities_list_view.dart b/lib/service_request_latest/views/components/activities_list_view.dart index 81e8cc4e..cb1b7932 100644 --- a/lib/service_request_latest/views/components/activities_list_view.dart +++ b/lib/service_request_latest/views/components/activities_list_view.dart @@ -68,7 +68,7 @@ class _ActivitiesListViewState extends State { //backgroundColor: const Color(0xfff8f9fb), body: Consumer(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) { activities = requestDetailProvider.currentWorkOrder!.data!.activities; - requestDetailProvider.lastVisitedRequestActivityId = (activities.isNotEmpty? activities.last.id :-1)!; + requestDetailProvider.lastVisitedRequestActivityId = (activities.isNotEmpty ? activities.last.id : -1)!; if (activities.isNotEmpty && (activities.last.activityStatus!.value == 14 || activities.last.activityStatus!.value == 19)) { disableNewActivity = true; } else { @@ -165,7 +165,7 @@ class _ActivitiesListViewState extends State { // backgroundColor: AppColor.getHistoryLogStatusColorByName(activity.activityStatus!.name!), backgroundColor: AppColor.primary10, ), - "drag_icon".toSvgAsset(height: 12, width: 23, color: AppColor.neutral160), + // "drag_icon".toSvgAsset(height: 12, width: 23, color: AppColor.neutral160), if (userProvider.user!.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.status?.value != 5 && requestDetailProvider.currentWorkOrder?.data?.status?.value != 3) Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -225,11 +225,6 @@ class _ActivitiesListViewState extends State { style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), ), 2.height, -//TODO description text not in api. -// Text( -// '${context.translation.date}: ${activity.currentSituation?.date}', -// style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), -// ), if (activity.activitySparePart?.comment?.isNotEmpty ?? false) ...[ const Divider().defaultStyle(context), 2.height, @@ -245,11 +240,26 @@ class _ActivitiesListViewState extends State { ], ], ).toShadowContainer(context, padding: 12, showShadow: false).onPress(() { -//TODO write onview detail method.. -// Navigator.push( -// context, -// MaterialPageRoute(builder: (context) => WorkOrderDetailsPage(workOrder: activity, serviceRequest: ServiceRequest())), -// ); + // if(requestDetailProvider.currentWorkOrder?.data?.status?.id ==3498){ + // requestDetailProvider.sparePartHelperModel = SparePartHelperModel( + // id: activity.id, + // workOrderId: requestDetailProvider.currentWorkOrder?.data?.requestId, + // comment: activity.activitySparePart?.comment, + // sparePartAttachments: activity.activitySparePart?.acitiySparePartAttachments ?? [], + // activityStatus: activity.activityStatus, + // sparePart: SparePart( + // id: activity.activitySparePart?.partCatalogItem?.id, + // partName: activity.activitySparePart?.partCatalogItem?.partName, + // partNo: activity.activitySparePart?.partCatalogItem?.partNumber, + // oracleCode: activity.activitySparePart?.partCatalogItem?.oracleCode), + // quantity: activity.activitySparePart?.quantity, + // activityStatusId: activity.activityStatus?.id, + // ); + // requestDetailProvider.updateSparePartHelperModel(requestDetailProvider.sparePartHelperModel); + // Navigator.of(context).push(MaterialPageRoute( + // builder: (_) => const SparePartRequest(), + // )); + // } }); } @@ -265,14 +275,27 @@ class _ActivitiesListViewState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ //TODO will be here when fixed from backend.. - StatusLabel( - label: activity.activityStatus?.name, - textColor: AppColor.white10, - // textColor: AppColor.getHistoryLogStatusTextColorByName(activity.activityStatus!.name!), - // backgroundColor: AppColor.getHistoryLogStatusColorByName(activity.activityStatus!.name!), - backgroundColor: AppColor.primary10, + Row( + children: [ + StatusLabel( + label: activity.activityStatus?.name, + textColor: AppColor.white10, + // textColor: AppColor.getHistoryLogStatusTextColorByName(activity.activityStatus!.name!), + // backgroundColor: AppColor.getHistoryLogStatusColorByName(activity.activityStatus!.name!), + backgroundColor: AppColor.primary10, + ), + 5.width, + StatusLabel( + label: activity.activityMaintenance?.activityType, + // textColor: AppColor.white10, + textColor: AppColor.getActivityTypeTextColor(activity.activityMaintenance?.activityType??''), + backgroundColor: AppColor.getActivityTypeBgColor(activity.activityMaintenance?.activityType??''), + // backgroundColor: AppColor.primary10, + ), + ], ), - "drag_icon".toSvgAsset(height: 12, width: 23, color: AppColor.neutral160), + + // "drag_icon".toSvgAsset(height: 12, width: 23, color: AppColor.neutral160), if (userProvider.user!.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.status?.value != 5 && requestDetailProvider.currentWorkOrder?.data?.status?.value != 3) Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -308,7 +331,7 @@ class _ActivitiesListViewState extends State { style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), ), 2.height, - if (activity.activityMaintenance?.assignedEmployee != null && activity.activityMaintenance!.assistantEmployees!.isNotEmpty) ...[ + if (activity.activityMaintenance?.assistantEmployees != null && activity.activityMaintenance!.assistantEmployees!.isNotEmpty) ...[ Text( '${context.translation.assistantEmployee}: ${activity.activityMaintenance?.assistantEmployees?.first.user?.userName}', style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), @@ -329,8 +352,21 @@ class _ActivitiesListViewState extends State { style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), ), ], + //need to add all info here... + // if(requestDetailProvider.currentWorkOrder?.data?.status?.id==3498)...[ + // const Divider().defaultStyle(context), + // 2.height, + // // Text( + // // activity.activityMaintenance?.technicalComment ?? "", + // // style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), + // // ), + // ] ], - ).toShadowContainer(context, padding: 12, showShadow: false); + ).toShadowContainer(context, padding: 12, showShadow: false).onPress(() { + if (requestDetailProvider.isReadOnlyRequest) { + onEditMaintenanceRequestPress(context: context, requestDetailProvider: requestDetailProvider, activity: activity); + } + }); } void onEditMaintenanceRequestPress({required BuildContext context, required ServiceRequestDetailProvider requestDetailProvider, required Activities activity}) async { @@ -391,7 +427,7 @@ class _ActivitiesListViewState extends State { } Navigator.of(context).push(MaterialPageRoute( - builder: (_) => const MaintenanceRequestForm(), + builder: (_) => MaintenanceRequestForm(), )); } } @@ -410,3 +446,14 @@ class ReorderWidget extends StatelessWidget { ); } } +class DummyClass extends StatelessWidget { + const DummyClass({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} + + + diff --git a/lib/service_request_latest/views/components/asset_detail_card.dart b/lib/service_request_latest/views/components/asset_detail_card.dart index f86b30ad..914b847d 100644 --- a/lib/service_request_latest/views/components/asset_detail_card.dart +++ b/lib/service_request_latest/views/components/asset_detail_card.dart @@ -27,27 +27,41 @@ class AssetDetailCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - StatusLabel( - label: requestDetailProvider.engineerUpdateWorkOrderHelperModel?.equipmentStatus?.name, - id: requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.id ?? 0, - radius: 4, - textColor: AppColor.white10, - backgroundColor: AppColor.getEquipmentStatusColor(context, requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.id ?? 0), + Row( + children: [ + StatusLabel( + label: requestDetailProvider.engineerUpdateWorkOrderHelperModel?.equipmentStatus?.name, + id: requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.id ?? 0, + radius: 4, + textColor: AppColor.white10, + backgroundColor: AppColor.getEquipmentStatusColor(context, requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.id ?? 0), + ), + 5.width, + StatusLabel( + label: requestDetailProvider.engineerUpdateWorkOrderHelperModel?.serviceType?.name, + id: requestDetailProvider.engineerUpdateWorkOrderHelperModel?.serviceType?.id ?? 0, + radius: 4, + textColor: AppColor.getActivityTypeTextColor(requestDetailProvider.engineerUpdateWorkOrderHelperModel!.serviceType?.name ?? ''), + backgroundColor: AppColor.getActivityTypeBgColor(requestDetailProvider.engineerUpdateWorkOrderHelperModel!.serviceType?.name ?? ''), + ), + ], ), - "edit_icon".toSvgAsset(height: 21, width: 21).onPress(() async{ - requestDetailProvider.refreshTimer = false; - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => VerifyAssetDetails( - isEdit: true, - ))); - requestDetailProvider.refreshTimer = true; - }), + //hide if status is closed or complete . + if (!requestDetailProvider.isReadOnlyRequest) + "edit_icon".toSvgAsset(height: 21, width: 21).onPress(() async { + requestDetailProvider.refreshTimer = false; + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => VerifyAssetDetails( + isEdit: true, + ))); + requestDetailProvider.refreshTimer = true; + }), ]), 6.height, Text( - context.translation.assetSituation, + "Work Order Details", style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), Text( diff --git a/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart b/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart index 150b59d8..6df66036 100644 --- a/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart +++ b/lib/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart @@ -704,7 +704,7 @@ class ServiceRequestBottomSheet { ); Navigator.pushReplacement( context, - MaterialPageRoute(builder: (context) => const MaintenanceRequestForm()), + MaterialPageRoute(builder: (context) => MaintenanceRequestForm()), ); break; } @@ -837,14 +837,14 @@ class ServiceRequestBottomSheet { } static bool validateAssetSituation(ServiceRequestDetailProvider requestDetailProvider) { - if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus != null) { - if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.value == 1 || requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.value == 2) { - if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.returnToService == null) { - Fluttertoast.showToast(msg: "Return to service is required ", toastLength: Toast.LENGTH_LONG); - return false; - } - } - } + // if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus != null) { + // if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.value == 1 || requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.value == 2) { + // if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.returnToService == null) { + // Fluttertoast.showToast(msg: "Return to service is required ", toastLength: Toast.LENGTH_LONG); + // return false; + // } + // } + // } return true; } diff --git a/lib/service_request_latest/views/components/service_request_detail_view.dart b/lib/service_request_latest/views/components/service_request_detail_view.dart index e804e248..c4d25e0e 100644 --- a/lib/service_request_latest/views/components/service_request_detail_view.dart +++ b/lib/service_request_latest/views/components/service_request_detail_view.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; @@ -19,13 +21,28 @@ import 'package:test_sa/service_request_latest/views/components/asset_detail_car import 'package:test_sa/service_request_latest/views/components/initial_visit_card.dart'; import 'package:test_sa/service_request_latest/views/components/timer_widget.dart'; import 'package:test_sa/service_request_latest/views/forms/asset_retired/asset_retired.dart'; -import 'package:test_sa/views/widgets/images/files_list.dart'; +import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart'; import 'package:test_sa/views/widgets/sound/sound_player.dart'; -class ServiceRequestDetailView extends StatelessWidget { - const ServiceRequestDetailView({Key? key}) : super(key: key); +class ServiceRequestDetailView extends StatefulWidget { + ServiceRequestDetailView({Key? key}) : super(key: key); + + @override + State createState() => _ServiceRequestDetailViewState(); +} + +class _ServiceRequestDetailViewState extends State { + List _workOrderAttachments = []; + + @override + void initState() { + ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); + _workOrderAttachments = requestDetailProvider.currentWorkOrder?.data?.workOrderAttachments.map((e) => File(e.name ?? '')).toList() ?? []; + // _workOrderAttachments = requestDetailProvider.currentWorkOrder?.data?.workOrderAttachments.map((e) => AttachmentModel(e.id??0, File(e.name ?? ''))).toList() ?? []; + super.initState(); + } @override Widget build(BuildContext context) { @@ -45,31 +62,34 @@ class ServiceRequestDetailView extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - workOrderDetailCard(context, requestProvider.currentWorkOrder!.data!, _userProvider), + workOrderDetailCard(context, requestProvider.currentWorkOrder!.data!, _userProvider, requestProvider), initialVisitCard(requestDetailProvider: requestProvider, userProvider: _userProvider), assetDetailCard(requestDetailProvider: requestProvider, userProvider: _userProvider), + 12.height, + contactInfoCard(context, requestProvider.currentWorkOrder!.data!), 20.height, ], ), ).expanded, FooterActionButton.requestDetailsFooterWidget( workOrderNextStepStatus: requestProvider.currentWorkOrder!.data!.nextStep!.workOrderNextStepEnum!, - // workOrderNextStepStatus: WorkOrderNextStepEnum.eNeedVisit, + status: requestProvider.currentWorkOrder?.data?.status, isEmpIsAssigned: requestProvider.currentWorkOrder!.data!.assignedEmployee != null, activities: requestProvider.currentWorkOrder!.data?.activities ?? [], userProvider: _userProvider, context: context), ], ), - if (requestProvider.timer != null && requestProvider.timer!.isActive) ...[ - const TimerWidget(), - ] + //no need to show timer as discussed with backend + // if (requestProvider.timer != null && requestProvider.timer!.isActive) ...[ + // const TimerWidget(), + // ] ], ); }); } - Widget workOrderDetailCard(BuildContext context, WorkOrderData workOrder, UserProvider userProvider) { + Widget workOrderDetailCard(BuildContext context, WorkOrderData workOrder, UserProvider userProvider, ServiceRequestDetailProvider requestProvider) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -100,6 +120,15 @@ class ServiceRequestDetailView extends StatelessWidget { textColor: AppColor.getHistoryLogStatusTextColorByName(workOrder.status!.name!), backgroundColor: AppColor.getHistoryLogStatusColorByName(workOrder.status!.name!), ), + if (workOrder.since != null) ...[ + 8.width, + StatusLabel( + radius: 4, + label: '${workOrder.since} days', + textColor: AppColor.neutral50, + backgroundColor: AppColor.orange30, + ), + ], 1.width.expanded, Column( crossAxisAlignment: CrossAxisAlignment.end, @@ -191,9 +220,18 @@ class ServiceRequestDetailView extends StatelessWidget { style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), Text( - 'Date/Time: ${workOrder.requestedDate!.toString().toServiceRequestDetailsFormat}', + 'Requested Date: ${workOrder.requestedDate!.toString().toServiceRequestDetailsFormat}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120), ), + Text( + '${context.translation.arrivedDate}: ${workOrder.iHaveArrivedDate != null ? workOrder.iHaveArrivedDate.toString().toServiceRequestDetailsFormat : '-'}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120), + ), + Text( + '${context.translation.closedDate}: ${workOrder.closedDate != null ? workOrder.closedDate!.toString().toServiceRequestDetailsFormat : '-'}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120), + ), + const Divider().defaultStyle(context), //... call response details starts here.... @@ -215,13 +253,40 @@ class ServiceRequestDetailView extends StatelessWidget { '${context.translation.activityStatus}: ${workOrder.lastActivityStatus?.name ?? "-"}', style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), + Text( + '${context.translation.callResponse}: ${workOrder.callResponse ?? "-"}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + ), + // Text( + // '${context.translation.since}: ${workOrder.since != null ? '${workOrder.since} days' : '-'}', + // style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + // ), + 8.height, + if (workOrder.rejectReason != null) ...[ + const Divider().defaultStyle(context), + 8.height, + Text( + context.translation.rejectionDetails, + style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ), + 8.height, + Text( + '${context.translation.rejectionReason}: ${workOrder.rejectReason?.name ?? '-'}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + ), + 8.height, + Text( + '${context.translation.comment}: ${workOrder.rejectComment ?? '-'}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + ), + ], 8.height, if ((workOrder.comments ?? "").isNotEmpty) ...[ const Divider().defaultStyle(context), 8.height, Text( - "Call Comment", + context.translation.callComments, style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), ), 8.height, @@ -230,11 +295,23 @@ class ServiceRequestDetailView extends StatelessWidget { style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), ), ], - if (workOrder.workOrderAttachments.isNotEmpty ?? false) ...[ + + if (!requestProvider.isReadOnlyRequest) ...[ 8.height, const Divider().defaultStyle(context), - FilesList(images: workOrder.workOrderAttachments.map((toElement) => URLs.getFileUrl(toElement.name ?? '') ?? '').toList()), + MultiFilesPicker( + label: context.translation.attachments, + files: _workOrderAttachments, + // attachment: _workOrderAttachments, + buttonColor: AppColor.primary10, + onlyImages: false, + buttonIcon: 'quotation_icon'.toSvgAsset(color: AppColor.primary10), + onChange: (attachment) { + requestProvider.addWorkOrderAttachment(woId: workOrder.requestId!, attachments: _workOrderAttachments); + }, + ), ], + if (workOrder.voiceNote?.isNotEmpty ?? false) ...[ const Divider().defaultStyle(context), 16.height, @@ -308,6 +385,55 @@ class ServiceRequestDetailView extends StatelessWidget { ).toShadowContainer(context, padding: 0); } + Widget contactInfoCard(BuildContext context, WorkOrderData workOrder) { + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Contact Info", + style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ), + 8.height, + ListView.separated( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + padding: EdgeInsets.zero, + itemBuilder: (cxt, index) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '${workOrder.workOrderContactPerson[index].name ?? '-'}', + style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ), + Text( + '${context.translation.employeeId}: ${workOrder.workOrderContactPerson[index].employeeId ?? '-'}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + ), + Text( + '${context.translation.telephone}: ${workOrder.workOrderContactPerson[index].mobilePhone ?? '-'}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + ), + Text( + 'Job: ${workOrder.workOrderContactPerson[index].position ?? '-'}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + ), + Text( + '${context.translation.email}: ${workOrder.workOrderContactPerson[index].email ?? '-'}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + ), + Text( + 'Extension: ${workOrder.workOrderContactPerson[index].extension ?? '-'}', + style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), + ), + ], + ), + separatorBuilder: (cxt, index) => const Divider().defaultStyle(context), + itemCount: workOrder.workOrderContactPerson.length), + ], + ).toShadowContainer(context, padding: 16); + } + Widget assetRetiredButton({required BuildContext context}) { return Padding( padding: EdgeInsets.symmetric(horizontal: 16.toScreenHeight, vertical: 12.toScreenWidth), @@ -347,7 +473,8 @@ class ServiceRequestDetailView extends StatelessWidget { } Widget assetDetailCard({required ServiceRequestDetailProvider requestDetailProvider, required UserProvider userProvider}) { - if (userProvider.user?.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.activity) { + if ((userProvider.user?.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.nextStep!.workOrderNextStepEnum == WorkOrderNextStepEnum.activity) || + requestDetailProvider.isReadOnlyRequest) { WorkOrderData currentWorkOrderData = requestDetailProvider.currentWorkOrder!.data!; requestDetailProvider.engineerUpdateWorkOrderHelperModel = EngineerUpdateWorkOrderHelperModel( workOrderId: currentWorkOrderData.requestId, diff --git a/lib/service_request_latest/views/forms/asset_retired/verify_asset_detail.dart b/lib/service_request_latest/views/forms/asset_retired/verify_asset_detail.dart index c0f9942e..6952d29b 100644 --- a/lib/service_request_latest/views/forms/asset_retired/verify_asset_detail.dart +++ b/lib/service_request_latest/views/forms/asset_retired/verify_asset_detail.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; -import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; @@ -14,6 +13,7 @@ import 'package:test_sa/models/new_models/work_order_detail_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart'; +import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart'; import 'package:test_sa/providers/loading_list_notifier.dart'; import 'package:test_sa/providers/service_request_providers/equipment_status_provider.dart'; @@ -75,6 +75,7 @@ class _VerifyAssetDetailsState extends State with TickerProv solution: currentWorkOrderData.faultDescription?.workPerformed, returnToService: currentWorkOrderData.returnToService, serviceType: currentWorkOrderData.serviceType, + callResponse: currentWorkOrderData.callResponse, ); if (currentWorkOrderData.assetLoan != null) { loanAvailabilityAsset = Asset( @@ -215,12 +216,27 @@ class _VerifyAssetDetailsState extends State with TickerProv } }, ), - 12.height, - context.translation.solutions.heading6(context).custom(color: AppColor.neutral50), + if (requestDetailProvider.engineerUpdateWorkOrderHelperModel?.solution != null) ...[ + 12.height, + context.translation.solutions.heading6(context).custom(color: AppColor.neutral50), + 8.height, + requestDetailProvider.engineerUpdateWorkOrderHelperModel?.solution != null + ? requestDetailProvider.engineerUpdateWorkOrderHelperModel!.solution!.bodyText2(context).custom(color: AppColor.neutral120,align: TextAlign.justify) + : const SizedBox(), + ], 8.height, - requestDetailProvider.engineerUpdateWorkOrderHelperModel?.solution != null - ? requestDetailProvider.engineerUpdateWorkOrderHelperModel!.solution!.bodyText2(context).custom(color: AppColor.neutral120) - : const SizedBox(), + AppTextFormField( + labelText: context.translation.callResponse, + backgroundColor: AppColor.neutral100, + initialValue: requestDetailProvider.engineerUpdateWorkOrderHelperModel?.callResponse, + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + showShadow: false, + onChange: (value){ + requestDetailProvider.engineerUpdateWorkOrderHelperModel?.callResponse = value; + }, + style: Theme.of(context).textTheme.titleMedium, + ), ], ).toShadowContainer(context).paddingAll(16), ).expanded, diff --git a/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart b/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart index 0e1764e7..6dd67f9e 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart @@ -39,6 +39,11 @@ class _AssistantEmployeeCardState extends State { Future getInitialData() async { final user = Provider.of(context, listen: false).user!; ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); + if( requestDetailProvider.isReadOnlyRequest){ + isExpanded = true; + setState(() { + }); + } isCurrentUserIsAssistantEmp = (user.userID != requestDetailProvider.currentWorkOrder?.data?.assignedEmployee?.userId); // if (isCurrentUserIsAssistantEmp) { @@ -122,7 +127,7 @@ class _AssistantEmployeeCardState extends State { requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); ServiceRequestUtils.calculateAndAssignWorkingHours( startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, - endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, + endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate, workingHoursController: _workingHoursController, updateModel: (hours){ requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours=hours; diff --git a/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_list.dart b/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_list.dart new file mode 100644 index 00000000..0b102c0f --- /dev/null +++ b/lib/service_request_latest/views/forms/maintenance_request/components/assistant_employee_list.dart @@ -0,0 +1,546 @@ +// // import 'package:flutter/material.dart'; +// // import 'package:fluttertoast/fluttertoast.dart'; +// // import 'package:provider/provider.dart'; +// // import 'package:test_sa/controllers/providers/api/user_provider.dart'; +// // import 'package:test_sa/extensions/context_extension.dart'; +// // import 'package:test_sa/extensions/int_extensions.dart'; +// // import 'package:test_sa/extensions/string_extensions.dart'; +// // import 'package:test_sa/extensions/text_extensions.dart'; +// // import 'package:test_sa/extensions/widget_extensions.dart'; +// // import 'package:test_sa/models/lookup.dart'; +// // import 'package:test_sa/models/plan_preventive_visit/plan_preventive_visit_model.dart'; +// // import 'package:test_sa/models/ppm/ppm_calibration_tools.dart'; +// // import 'package:test_sa/models/service_request/supplier_details.dart'; +// // import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +// // import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; +// // import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart'; +// // import 'package:test_sa/providers/loading_list_notifier.dart'; +// // import 'package:test_sa/providers/ppm_service_provider.dart'; +// // import 'package:test_sa/providers/work_order/vendor_provider.dart'; +// // import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; +// // import 'package:test_sa/views/widgets/pentry/calibration_tool_asset_picker.dart'; +// // +// // import '../../../../../new_views/app_style/app_color.dart'; +// // import '../../../../widgets/date_and_time/date_picker.dart'; +// // +// // class AssistantEmployeeList extends StatefulWidget { +// // final List? models; +// // +// // const AssistantEmployeeList({Key? key, this.models = const []}) : super(key: key); +// // +// // @override +// // State createState() => _AssistantEmployeeListState(); +// // } +// // +// // class _AssistantEmployeeListState extends State { +// // final TextEditingController _workingHoursController = TextEditingController(); +// // +// // @override +// // Widget build(BuildContext context) { +// // return ListView.builder( +// // itemCount: widget.models!.length + 1, +// // padding: const EdgeInsets.only(left: 16, right: 16, top: 8, bottom: 16), +// // itemBuilder: (context, index) { +// // if (index == widget.models!.length) { +// // return AppFilledButton( +// // label: "Add More External Details".addTranslation, +// // maxWidth: true, +// // textColor: AppColor.black10, +// // buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, +// // icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), +// // showIcon: true, +// // onPressed: () async { +// // // if (widget.models?.isNotEmpty ?? false) { +// // // if (widget.models!.last.assetId == null) { +// // // await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.assetNumber}"); +// // // return; +// // // } +// // // if (widget.models!.last.calibrationDateOfTesters == null) { +// // // await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.date}"); +// // // return; +// // // } +// // // } +// // // widget.models!.add(PpmCalibrationTools(id: 0)); +// // // setState(() {}); +// // }, +// // ); +// // } +// // final model = widget.models![index]; +// // // _workingHoursController.text = model.workingHours != null ? model.workingHours.toString() : ''; +// // return Container( +// // padding: const EdgeInsets.all(16), +// // margin: EdgeInsets.only(bottom: 16.toScreenHeight), +// // decoration: BoxDecoration( +// // color: AppColor.background(context), +// // borderRadius: BorderRadius.circular(20), +// // boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], +// // ), +// // child: Column( +// // crossAxisAlignment: CrossAxisAlignment.start, +// // children: [ +// // Row( +// // mainAxisAlignment: MainAxisAlignment.spaceBetween, +// // children: [ +// // (index == 0 ? "1 /4 . External Details" : "").heading5(context), +// // "trash".toSvgAsset(height: 20, width: 15).onPress(() { +// // widget.models!.remove(model); +// // +// // setState(() {}); +// // }), +// // ], +// // ), +// // 16.height, +// // SingleItemDropDownMenu( +// // context: context, +// // title: context.translation.supplier, +// // initialValue: model.supplier, +// // backgroundColor: AppColor.neutral100, +// // showAsBottomSheet: true, +// // onSelect: (supplier) { +// // if (supplier != null) { +// // model.supplier = supplier; +// // print('supplier dtails is ${supplier.toJson()}'); +// // setState(() {}); +// // } +// // }, +// // ), +// // 8.height, +// // SingleItemDropDownMenu( +// // context: context, +// // title: context.translation.supplierEngineer, +// // enabled: model.suppPerson != null, +// // backgroundColor: AppColor.neutral100, +// // initialValue: model.suppPerson, +// // staticData: model.supplier?.suppPersons, +// // showAsBottomSheet: true, +// // onSelect: (suppPerson) { +// // if (suppPerson != null) { +// // model.suppPerson = suppPerson; +// // print('supply person is ${model.suppPerson?.toJson()}'); +// // } +// // }, +// // ), +// // 8.height, +// // AppTextFormField( +// // labelText: "Telephone", +// // initialValue: model.supplier?.telephones != null && model.supplier!.telephones!.isNotEmpty ? (model.supplier?.telephones?[0].telephone ?? "").toString() : '', +// // textAlign: TextAlign.center, +// // backgroundColor: AppColor.neutral100, +// // style: Theme.of(context).textTheme.titleMedium, +// // textInputType: TextInputType.number, +// // onChange: (value) { +// // model.supplier?.telephones?[0].telephone = value; +// // }, +// // ), +// // 8.height, +// // Row( +// // mainAxisSize: MainAxisSize.min, +// // children: [ +// // ADatePicker( +// // label: context.translation.startTime, +// // hideShadow: true, +// // backgroundColor: AppColor.neutral100, +// // date: model.startDateTime, +// // formatDateWithTime: true, +// // onDatePicker: (selectedDate) { +// // showTimePicker( +// // context: context, +// // initialTime: TimeOfDay.now(), +// // ).then((selectedTime) { +// // // Handle the selected date and time here. +// // if (selectedTime != null) { +// // DateTime selectedDateTime = DateTime( +// // selectedDate.year, +// // selectedDate.month, +// // selectedDate.day, +// // selectedTime.hour, +// // selectedTime.minute, +// // ); +// // setState(() { +// // model.startDateTime = selectedDateTime; +// // }); +// // model.endDateTime = null; +// // _workingHoursController.clear(); +// // ServiceRequestUtils.calculateAndAssignWorkingHours( +// // startTime: model.startDateTime, +// // endTime: model.endDateTime, +// // workingHoursController: _workingHoursController, +// // updateModel: (hours) { +// // model.workingHours = hours; +// // }, +// // ); +// // } +// // }); +// // }, +// // ).expanded, +// // 8.width, +// // ADatePicker( +// // label: context.translation.endTime, +// // hideShadow: true, +// // backgroundColor: AppColor.neutral100, +// // date: model.endDateTime, +// // formatDateWithTime: true, +// // onDatePicker: (selectedDate) { +// // showTimePicker( +// // context: context, +// // initialTime: TimeOfDay.now(), +// // ).then((selectedTime) { +// // // Handle the selected date and time here. +// // if (selectedTime != null) { +// // DateTime selectedDateTime = DateTime( +// // selectedDate.year, +// // selectedDate.month, +// // selectedDate.day, +// // selectedTime.hour, +// // selectedTime.minute, +// // ); +// // if (model.startDateTime != null && selectedDateTime.isBefore(model.startDateTime!)) { +// // "End Date time must be greater then start date".showToast; +// // return; +// // } +// // model.endDateTime = selectedDateTime; +// // setState(() {}); +// // ServiceRequestUtils.calculateAndAssignWorkingHours( +// // startTime: model.startDateTime, +// // endTime: model.endDateTime, +// // workingHoursController: _workingHoursController, +// // updateModel: (hours) { +// // model.workingHours = hours; +// // }, +// // ); +// // } +// // }); +// // }, +// // ).expanded, +// // ], +// // ), +// // 8.height, +// // AppTextFormField( +// // labelText: context.translation.workingHours, +// // backgroundColor: AppColor.neutral80, +// // controller: _workingHoursController, +// // suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), +// // // initialValue: model.workingHours != null ? model.workingHours.toString() : '', +// // textAlign: TextAlign.center, +// // labelStyle: AppTextStyles.textFieldLabelStyle, +// // enable: false, +// // showShadow: false, +// // style: Theme.of(context).textTheme.titleMedium, +// // ), +// // 8.height, +// // ], +// // ), +// // ); +// // }, +// // ); +// // } +// // } +// +// import 'package:flutter/material.dart'; +// import 'package:provider/provider.dart'; +// import 'package:test_sa/controllers/providers/api/ppm_provider.dart'; +// import 'package:test_sa/controllers/providers/api/user_provider.dart'; +// import 'package:test_sa/extensions/context_extension.dart'; +// import 'package:test_sa/extensions/int_extensions.dart'; +// import 'package:test_sa/extensions/string_extensions.dart'; +// import 'package:test_sa/extensions/text_extensions.dart'; +// import 'package:test_sa/extensions/widget_extensions.dart'; +// import 'package:test_sa/models/new_models/assistant_employee.dart'; +// import 'package:test_sa/models/new_models/work_order_detail_model.dart'; +// import 'package:test_sa/new_views/app_style/app_color.dart'; +// import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +// import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; +// import 'package:test_sa/service_request_latest/service_request_detail_provider.dart'; +// import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; +// import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; +// import 'package:test_sa/views/widgets/status/report/service_report_assistant_employee_menu.dart'; +// +// class AssistantEmployeeList extends StatefulWidget { +// final List? models; +// +// const AssistantEmployeeList({Key? key, this.models = const []}) : super(key: key); +// +// @override +// State createState() => _AssistantEmployeeListState(); +// } +// +// class _AssistantEmployeeListState extends State { +// bool isLoading = false; +// +// //TODO add loader when adding or deleting item.. +// +// void _addNewEntry() { +// setState(() { +// // isLoading = true; +// widget.models!.add(ActivityMaintenanceAssistantEmployees()); +// // Future.delayed(Duration(seconds: 1)).whenComplete(() { +// // setState(() { +// // isLoading = false; +// // }); +// // }); +// }); +// } +// +// void _removeEntry(int index) { +// setState(() { +// isLoading = true; +// widget.models!.removeAt(index); +// // isLoading = false; +// }); +// } +// +// @override +// Widget build(BuildContext context) { +// final ppmProvider = Provider.of(context, listen: false); +// return ListView.builder( +// itemCount: widget.models!.length + 1, +// padding: const EdgeInsets.all(16), +// itemBuilder: (context, index) { +// if (index == widget.models!.length) { +// return Visibility( +// visible: !ppmProvider.isReadOnly, +// child: AppFilledButton( +// label: "Add More Assistant Employees".addTranslation, +// maxWidth: true, +// textColor: AppColor.black10, +// buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, +// icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), +// showIcon: true, +// onPressed: _addNewEntry, +// ), +// ); +// } +// // return !isLoading +// // ? +// return AssistantEmployeeItem( +// model: widget.models![index], +// // index: index, +// // onRemove: () => _removeEntry(index), +// ); +// // : const ALoading(); +// }, +// ); +// } +// } +// class AssistantEmployeeItem extends StatefulWidget { +// final ActivityMaintenanceAssistantEmployees model; +// const AssistantEmployeeItem({required this.model,super.key}); +// +// @override +// State createState() => _AssistantEmployeeItemState(); +// } +// +// class _AssistantEmployeeItemState extends State { +// bool status = false; +// final TextEditingController _workingHoursController = TextEditingController(text: ''); +// bool isCurrentUserIsAssistantEmp = false; +// bool isExpanded = false; +// +// @override +// void initState() { +// // TODO: implement initState +// WidgetsBinding.instance.addPostFrameCallback((_) { +// getInitialData(); +// }); +// super.initState(); +// } +// +// Future getInitialData() async { +// final user = Provider.of(context, listen: false).user!; +// ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); +// if( requestDetailProvider.isReadOnlyRequest){ +// isExpanded = true; +// setState(() { +// }); +// } +// isCurrentUserIsAssistantEmp = (user.userID != requestDetailProvider.currentWorkOrder?.data?.assignedEmployee?.userId); +// +// // if (isCurrentUserIsAssistantEmp) { +// // // _subWorkOrders.assistantEmployees = [widget.workOrder.assistantEmployees?.first?.copyWith(id: 0)]; +// // } +// } +// +// @override +// void dispose() { +// // TODO: implement dispose +// _workingHoursController.dispose(); +// super.dispose(); +// } +// +// @override +// Widget build(BuildContext context) { +// return Consumer(builder: (context, requestDetailProvider, child) { +// return Column( +// children: [ +// SizedBox( +// height: 56.toScreenHeight, +// child: Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// context.translation.assistantEmployee.bodyText(context).custom(color: AppColor.black20), +// Icon(isExpanded ? Icons.arrow_drop_up_outlined : Icons.arrow_drop_down), +// ], +// ), +// ).onPress(() { +// setState(() { +// isExpanded = !isExpanded; +// }); +// }), +// isExpanded +// ? Column( +// crossAxisAlignment: CrossAxisAlignment.stretch, +// children: [ +// ServiceReportAssistantEmployeeMenu( +// title: context.translation.select, +// backgroundColor: AppColor.neutral100, +// assetId: requestDetailProvider.currentWorkOrder!.data!.asset!.id!, +// initialValue: widget.model., +// onSelect: (employee) { +// if (employee == null) { +// requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployees = []; +// } else { +// widget.model = [employee.copyWith(id: 0)]; +// // requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.user = AssignedEmployee(userId: employee.user?.id, userName: employee.user?.name); +// } +// }, +// ), +// 8.height, +// Row( +// mainAxisSize: MainAxisSize.min, +// children: [ +// ADatePicker( +// label: context.translation.startTime, +// hideShadow: true, +// backgroundColor: AppColor.neutral100, +// date: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, +// formatDateWithTime: true, +// onDatePicker: (selectedDate) { +// showTimePicker( +// context: context, +// initialTime: TimeOfDay.now(), +// ).then((selectedTime) { +// // Handle the selected date and time here. +// if (selectedTime != null) { +// DateTime selectedDateTime = DateTime( +// selectedDate.year, +// selectedDate.month, +// selectedDate.day, +// selectedTime.hour, +// selectedTime.minute, +// ); +// requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate = selectedDateTime; +// requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); +// ServiceRequestUtils.calculateAndAssignWorkingHours( +// startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, +// endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, +// workingHoursController: _workingHoursController, +// updateModel: (hours){ +// requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours=hours; +// }); +// } +// }); +// }, +// ).expanded, +// 8.width, +// ADatePicker( +// label: context.translation.endTime, +// hideShadow: true, +// backgroundColor: AppColor.neutral100, +// date: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate, +// formatDateWithTime: true, +// onDatePicker: (selectedDate) { +// showTimePicker( +// context: context, +// initialTime: TimeOfDay.now(), +// ).then((selectedTime) { +// // Handle the selected date and time here. +// if (selectedTime != null) { +// DateTime selectedDateTime = DateTime( +// selectedDate.year, +// selectedDate.month, +// selectedDate.day, +// selectedTime.hour, +// selectedTime.minute, +// ); +// if (requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate != null && +// selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.startDate!)) { +// "End Date time must be greater then start date".showToast; +// return; +// } +// requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate = selectedDateTime; +// requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); +// ServiceRequestUtils.calculateAndAssignWorkingHours( +// startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, +// endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate, +// workingHoursController: _workingHoursController, +// updateModel: (hours){ +// requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours=hours; +// }); +// } +// }); +// }, +// ).expanded, +// ], +// ), +// 8.height, +// AppTextFormField( +// labelText: context.translation.workingHours, +// backgroundColor: AppColor.neutral80, +// controller: _workingHoursController, +// suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), +// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.workingHours != null +// ? requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours.toString() +// : '', +// textAlign: TextAlign.center, +// labelStyle: AppTextStyles.textFieldLabelStyle, +// enable: false, +// showShadow: false, +// style: Theme.of(context).textTheme.titleMedium, +// ), +// 8.height, +// AppTextFormField( +// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment, +// labelText: context.translation.technicalComment, +// backgroundColor: AppColor.neutral100, +// showShadow: false, +// labelStyle: AppTextStyles.textFieldLabelStyle, +// alignLabelWithHint: true, +// textInputType: TextInputType.multiline, +// onChange: (value) { +// requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment = value; +// }, +// onSaved: (value) { +// requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment = value; +// }, +// ), +// 8.height, +// ], +// ) +// : const SizedBox(), +// ], +// ); +// }); +// } +// +// // //TODO move this to some common place....@waseem +// // double calculateWorkingHours(DateTime? startTime, DateTime? endTime) { +// // if (startTime != null && endTime != null) { +// // Duration difference = endTime.difference(startTime); +// // int hours = difference.inHours; +// // int minutes = difference.inMinutes % 60; +// // return hours.toDouble(); +// // } else { +// // return -1; +// // } +// // } +// // +// // assignWorkingHours({required RequestDetailProvider requestDetailProvider}) { +// // double hours = calculateWorkingHours( +// // requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate); +// // if (hours != -1) { +// // _workingHoursController.text = hours.toString(); +// // requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.workingHours = hours; +// // } +// // } +// } +// diff --git a/lib/service_request_latest/views/forms/maintenance_request/components/external_request.dart b/lib/service_request_latest/views/forms/maintenance_request/components/external_request.dart index e3727b7f..1f828514 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/components/external_request.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/components/external_request.dart @@ -42,198 +42,198 @@ class _ExternalMaintenanceRequestState extends State ServiceRequestDetailProvider requestDetailProvider = Provider.of(context, listen: false); _workingHoursController.text = requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour != null ? requestDetailProvider.activityMaintenanceHelperModel!.supplierWorkingHour.toString() : ''; - } @override Widget build(BuildContext context) { return Consumer(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) { - return Column( - children: [ - Form( - key: _formKey, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - SingleItemDropDownMenu( - context: context, - title: context.translation.supplier, - backgroundColor: AppColor.neutral100, - initialValue: requestDetailProvider.activityMaintenanceHelperModel?.supplier, - showAsBottomSheet: true, - onSelect: (supplier) { - if (supplier != null) { - requestDetailProvider.activityMaintenanceHelperModel?.supplier = supplier; - // _subWorkOrders.supplier = supplier; - // log(_subWorkOrders.supplier?.suppPersons?.map((e) => e.personName)?.toString()); - setState(() {}); - } - }, - ), - 8.height, - Row( - children: [ - SingleItemDropDownMenu( - context: context, - backgroundColor: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null ? AppColor.neutral40 : AppColor.neutral100, - title: context.translation.supplierEngineer, - enabled: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons?.isNotEmpty ?? false, - staticData: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons, - showAsBottomSheet: true, - initialValue: requestDetailProvider.activityMaintenanceHelperModel?.supEngineer == null - ? null - : SuppPersons.fromJson(requestDetailProvider.activityMaintenanceHelperModel?.supEngineer?.toJson()), - onSelect: (suppPerson) { - print(suppPerson?.toJson()); - if (suppPerson != null) { - requestDetailProvider.activityMaintenanceHelperModel?.supEngineer = SuppEngineerWorkOrders.fromJson(suppPerson.toJson()); - requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); - // engineer = SuppEngineerWorkOrders( - // id: suppPerson?.supplierId, - // supplierContactId: suppPerson?.id, - // personName: suppPerson?.personName, - // contact: suppPerson?.contact, - // externalEngCode: suppPerson?.externalEngCode, - // email: suppPerson?.email, - // ); - setState(() {}); - } - }, - ).expanded, - 8.width, - Container( - height: 56.toScreenHeight, - width: 60.toScreenWidth, - decoration: BoxDecoration( - color: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null ? AppColor.neutral40 : AppColor.neutral100, - borderRadius: BorderRadius.circular(10), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], - ), - child: Icon( - Icons.add, - color: context.isDark ? null : AppColor.neutral60, - ), - ).onPress(requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null - ? null - : () async { - SuppEngineerWorkOrders suppEngineer = (await showModalBottomSheet( - context: context, - useSafeArea: true, - isScrollControlled: true, - backgroundColor: Colors.transparent, - builder: (context) => AddSupplierEngineerBottomSheet(requestDetailProvider.activityMaintenanceHelperModel!.supplier!.id!.toInt()), - )) as SuppEngineerWorkOrders; - requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons ??= []; - requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons?.add(SuppPersons.fromJson(suppEngineer.toJson())); - requestDetailProvider.activityMaintenanceHelperModel?.supEngineer = suppEngineer; - setState(() {}); - }), - ], - ), - 8.height, - Row( - mainAxisSize: MainAxisSize.min, - children: [ - ADatePicker( - label: context.translation.startTime, - hideShadow: true, - backgroundColor: AppColor.neutral100, - date: requestDetailProvider.activityMaintenanceHelperModel?.supplierStartTime, - formatDateWithTime: true, - onDatePicker: (selectedDate) { - showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ).then((selectedTime) { - // Handle the selected date and time here. - if (selectedTime != null) { - DateTime selectedDateTime = DateTime( - selectedDate.year, - selectedDate.month, - selectedDate.day, - selectedTime.hour, - selectedTime.minute, - ); - requestDetailProvider.activityMaintenanceHelperModel?.supplierStartTime = selectedDateTime; - requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime = null; + return IgnorePointer( + ignoring: requestDetailProvider.isReadOnlyRequest, + child: Column( + children: [ + Form( + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SingleItemDropDownMenu( + context: context, + title: context.translation.supplier, + backgroundColor: AppColor.neutral100, + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.supplier, + showAsBottomSheet: true, + onSelect: (supplier) { + if (supplier != null) { + requestDetailProvider.activityMaintenanceHelperModel?.supplier = supplier; + // _subWorkOrders.supplier = supplier; + // log(_subWorkOrders.supplier?.suppPersons?.map((e) => e.personName)?.toString()); + setState(() {}); + } + }, + ), + 8.height, + Row( + children: [ + SingleItemDropDownMenu( + context: context, + backgroundColor: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null ? AppColor.neutral40 : AppColor.neutral100, + title: context.translation.supplierEngineer, + enabled: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons?.isNotEmpty ?? false, + staticData: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons, + showAsBottomSheet: true, + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.supEngineer == null + ? null + : SuppPersons.fromJson(requestDetailProvider.activityMaintenanceHelperModel?.supEngineer?.toJson()), + onSelect: (suppPerson) { + print(suppPerson?.toJson()); + if (suppPerson != null) { + requestDetailProvider.activityMaintenanceHelperModel?.supEngineer = SuppEngineerWorkOrders.fromJson(suppPerson.toJson()); requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); - _workingHoursController.clear(); - ServiceRequestUtils.calculateAndAssignWorkingHours( - startTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime, - endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime, - workingHoursController: _workingHoursController, - updateModel: (hours) { - requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour = hours; - }, - ); - + // engineer = SuppEngineerWorkOrders( + // id: suppPerson?.supplierId, + // supplierContactId: suppPerson?.id, + // personName: suppPerson?.personName, + // contact: suppPerson?.contact, + // externalEngCode: suppPerson?.externalEngCode, + // email: suppPerson?.email, + // ); + setState(() {}); } - }); - }, - ).expanded, - 8.width, - ADatePicker( - label: context.translation.endTime, - hideShadow: true, - backgroundColor: AppColor.neutral100, - date: requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime, - formatDateWithTime: true, - onDatePicker: (selectedDate) { - showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ).then((selectedTime) { - // Handle the selected date and time here. - if (selectedTime != null) { - DateTime selectedDateTime = DateTime( - selectedDate.year, - selectedDate.month, - selectedDate.day, - selectedTime.hour, - selectedTime.minute, - ); - if (requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime != null && - selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime!)) { - "End Date time must be greater then start date".showToast; - return; + }, + ).expanded, + 8.width, + Container( + height: 56.toScreenHeight, + width: 60.toScreenWidth, + decoration: BoxDecoration( + color: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null ? AppColor.neutral40 : AppColor.neutral100, + borderRadius: BorderRadius.circular(10), + boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], + ), + child: Icon( + Icons.add, + color: context.isDark ? null : AppColor.neutral60, + ), + ).onPress(requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null + ? null + : () async { + SuppEngineerWorkOrders suppEngineer = (await showModalBottomSheet( + context: context, + useSafeArea: true, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => AddSupplierEngineerBottomSheet(requestDetailProvider.activityMaintenanceHelperModel!.supplier!.id!.toInt()), + )) as SuppEngineerWorkOrders; + requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons ??= []; + requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons?.add(SuppPersons.fromJson(suppEngineer.toJson())); + requestDetailProvider.activityMaintenanceHelperModel?.supEngineer = suppEngineer; + setState(() {}); + }), + ], + ), + 8.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + ADatePicker( + label: context.translation.startTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: requestDetailProvider.activityMaintenanceHelperModel?.supplierStartTime, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + requestDetailProvider.activityMaintenanceHelperModel?.supplierStartTime = selectedDateTime; + requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime = null; + requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + _workingHoursController.clear(); + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime, + endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime, + workingHoursController: _workingHoursController, + updateModel: (hours) { + requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour = hours; + }, + ); } - requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime = selectedDateTime; - requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); - ServiceRequestUtils.calculateAndAssignWorkingHours( - startTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime, - endTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierEndTime, - workingHoursController: _workingHoursController, - updateModel: (hours) { - requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour = hours; - }, - ); - } - }); - }, - ).expanded, - ], - ), - 8.height, - AppTextFormField( - labelText: context.translation.workingHours, - backgroundColor: AppColor.neutral80, - controller: _workingHoursController, - suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), - initialValue: - requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour != null ? requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour.toString() : '', - textAlign: TextAlign.center, - labelStyle: AppTextStyles.textFieldLabelStyle, - enable: false, - showShadow: false, - style: Theme.of(context).textTheme.titleMedium, - ), - 8.height, - ], - ), - ).toShadowContainer(context).paddingOnly(start: 16, end: 16, top: 12), - ], + }); + }, + ).expanded, + 8.width, + ADatePicker( + label: context.translation.endTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + if (requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime != null && + selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime!)) { + "End Date time must be greater then start date".showToast; + return; + } + requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime = selectedDateTime; + requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime, + endTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierEndTime, + workingHoursController: _workingHoursController, + updateModel: (hours) { + requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour = hours; + }, + ); + } + }); + }, + ).expanded, + ], + ), + 8.height, + AppTextFormField( + labelText: context.translation.workingHours, + backgroundColor: AppColor.neutral80, + controller: _workingHoursController, + suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), + initialValue: + requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour != null ? requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour.toString() : '', + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + enable: false, + showShadow: false, + style: Theme.of(context).textTheme.titleMedium, + ), + 8.height, + ], + ), + ).toShadowContainer(context).paddingOnly(start: 16, end: 16, top: 12), + ], + ), ); }); } - } diff --git a/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart b/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart index c611ec97..c94195d4 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/components/internal_request.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + 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'; @@ -32,6 +34,7 @@ class _InternalMaintenanceRequestState extends State final TextEditingController _travellingHoursController = TextEditingController(); Lookup statusLookup = Lookup.fromJson({"id": 5619, "name": "New", "value": 1}); + @override void initState() { _requestDetailProvider = Provider.of(context, listen: false); @@ -53,8 +56,6 @@ class _InternalMaintenanceRequestState extends State @override Widget build(BuildContext context) { return Consumer(builder: (context, requestDetailProvider, child) { - - double totalWorkingHours = _requestDetailProvider?.activityMaintenanceHelperModel?.activityMaintenanceTimers ?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endTime!).difference(DateTime.parse(item.startTime!)).inSeconds) ?? 0; @@ -64,228 +65,231 @@ class _InternalMaintenanceRequestState extends State : requestDetailProvider.activityMaintenanceHelperModel?.id == requestDetailProvider.lastVisitedRequestActivityId; return SingleChildScrollView( - child: Column( - children: [ - Form( - key: _formKey, - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - // SingleItemDropDownMenu( - // context: context, - // height: 56.toScreenHeight, - // title: context.translation.activityStatus, - // showShadow: false, - // backgroundColor: AppColor.neutral100, - // initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus, - // onSelect: (status) { - // print('status i got is ${status?.toJson()}'); - // requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status; - // }, - // ), - // 8.height, - SingleItemDropDownMenu( - context: context, - height: 56.toScreenHeight, - title: context.translation.activityStatus, - showShadow: false, - backgroundColor: AppColor.neutral100, - showAsBottomSheet: true, - initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus, - onSelect: (status) { - if (status != null) { - requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status; - setState(() {}); - } - }, - ), - 8.height, - AppTimer( - label: context.translation.timer, - timer: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel, - enabled: enableTimer, - timerProgress: (isRunning) { - print("timerProgress:$isRunning"); - }, - onChange: (timer) async { - requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel = timer; - if (timer.startAt != null && timer.endAt != null) { - requestDetailProvider.activityMaintenanceHelperModel?.timerModelList = requestDetailProvider.activityMaintenanceHelperModel?.timerModelList ?? []; - requestDetailProvider.activityMaintenanceHelperModel?.timerModelList!.add(timer); - } - return true; - }, - ), - // Row( - // mainAxisSize: MainAxisSize.min, - // children: [ - // ADatePicker( - // label: context.translation.startTime, - // hideShadow: true, - // backgroundColor: AppColor.neutral100, - // date: requestDetailProvider.activityMaintenanceHelperModel?.startTime, - // formatDateWithTime: true, - // onDatePicker: (selectedDate) { - // showTimePicker( - // context: context, - // initialTime: TimeOfDay.now(), - // ).then((selectedTime) { - // // Handle the selected date and time here. - // if (selectedTime != null) { - // DateTime selectedDateTime = DateTime( - // selectedDate.year, - // selectedDate.month, - // selectedDate.day, - // selectedTime.hour, - // selectedTime.minute, - // ); - // requestDetailProvider.activityMaintenanceHelperModel?.startTime = selectedDateTime; - // requestDetailProvider.activityMaintenanceHelperModel?.endTime = null; - // requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); - // _workingHoursController.clear(); - // ServiceRequestUtils.calculateAndAssignWorkingHours( - // startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime, - // endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime, - // workingHoursController: _workingHoursController, - // updateModel: (hours) { - // requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours; - // }, - // ); - // } - // }); - // }, - // ).expanded, - // 8.width, - // ADatePicker( - // label: context.translation.endTime, - // hideShadow: true, - // backgroundColor: AppColor.neutral100, - // date: requestDetailProvider.activityMaintenanceHelperModel?.endTime, - // formatDateWithTime: true, - // onDatePicker: (selectedDate) { - // showTimePicker( - // context: context, - // initialTime: TimeOfDay.now(), - // ).then((selectedTime) { - // // Handle the selected date and time here. - // if (selectedTime != null) { - // DateTime selectedDateTime = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute); - // if (requestDetailProvider.activityMaintenanceHelperModel!.startTime != null && - // selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.startTime!)) { - // "End Date time must be greater then start date".showToast; - // return; - // } - // requestDetailProvider.activityMaintenanceHelperModel?.endTime = selectedDateTime; - // requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); - // ServiceRequestUtils.calculateAndAssignWorkingHours( - // startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime, - // endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime, - // workingHoursController: _workingHoursController, - // updateModel: (hours) { - // requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours; - // }, - // ); - // } - // }); - // }, - // ).expanded, - // ], - // ), - 8.height, - if (totalWorkingHours > 0.0) ...[ - Container( + child: IgnorePointer( + ignoring: _requestDetailProvider!.isReadOnlyRequest, + child: Column( + children: [ + Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // SingleItemDropDownMenu( + // context: context, + // height: 56.toScreenHeight, + // title: context.translation.activityStatus, + // showShadow: false, + // backgroundColor: AppColor.neutral100, + // initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus, + // onSelect: (status) { + // print('status i got is ${status?.toJson()}'); + // requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status; + // }, + // ), + // 8.height, + SingleItemDropDownMenu( + context: context, height: 56.toScreenHeight, - padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), - alignment: Alignment.centerLeft, - decoration: BoxDecoration( - color: context.isDark ? AppColor.neutral40 : AppColor.background(context), - borderRadius: BorderRadius.circular(10), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "Total Working Time", - style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), - ), - Text( - " ${ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round())}", - style: Theme.of(context).textTheme.bodyMedium, - ), - ], + title: context.translation.activityStatus, + showShadow: false, + backgroundColor: AppColor.neutral100, + showAsBottomSheet: true, + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus, + onSelect: (status) { + if (status != null) { + requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status; + setState(() {}); + } + }, + ), + 8.height, + AppTimer( + label: context.translation.timer, + timer: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel, + enabled: enableTimer, + timerProgress: (isRunning) { + print("timerProgress:$isRunning"); + }, + onChange: (timer) async { + requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel = timer; + if (timer.startAt != null && timer.endAt != null) { + requestDetailProvider.activityMaintenanceHelperModel?.timerModelList = requestDetailProvider.activityMaintenanceHelperModel?.timerModelList ?? []; + requestDetailProvider.activityMaintenanceHelperModel?.timerModelList!.add(timer); + } + return true; + }, + ), + // Row( + // mainAxisSize: MainAxisSize.min, + // children: [ + // ADatePicker( + // label: context.translation.startTime, + // hideShadow: true, + // backgroundColor: AppColor.neutral100, + // date: requestDetailProvider.activityMaintenanceHelperModel?.startTime, + // formatDateWithTime: true, + // onDatePicker: (selectedDate) { + // showTimePicker( + // context: context, + // initialTime: TimeOfDay.now(), + // ).then((selectedTime) { + // // Handle the selected date and time here. + // if (selectedTime != null) { + // DateTime selectedDateTime = DateTime( + // selectedDate.year, + // selectedDate.month, + // selectedDate.day, + // selectedTime.hour, + // selectedTime.minute, + // ); + // requestDetailProvider.activityMaintenanceHelperModel?.startTime = selectedDateTime; + // requestDetailProvider.activityMaintenanceHelperModel?.endTime = null; + // requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + // _workingHoursController.clear(); + // ServiceRequestUtils.calculateAndAssignWorkingHours( + // startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime, + // endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime, + // workingHoursController: _workingHoursController, + // updateModel: (hours) { + // requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours; + // }, + // ); + // } + // }); + // }, + // ).expanded, + // 8.width, + // ADatePicker( + // label: context.translation.endTime, + // hideShadow: true, + // backgroundColor: AppColor.neutral100, + // date: requestDetailProvider.activityMaintenanceHelperModel?.endTime, + // formatDateWithTime: true, + // onDatePicker: (selectedDate) { + // showTimePicker( + // context: context, + // initialTime: TimeOfDay.now(), + // ).then((selectedTime) { + // // Handle the selected date and time here. + // if (selectedTime != null) { + // DateTime selectedDateTime = DateTime(selectedDate.year, selectedDate.month, selectedDate.day, selectedTime.hour, selectedTime.minute); + // if (requestDetailProvider.activityMaintenanceHelperModel!.startTime != null && + // selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.startTime!)) { + // "End Date time must be greater then start date".showToast; + // return; + // } + // requestDetailProvider.activityMaintenanceHelperModel?.endTime = selectedDateTime; + // requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); + // ServiceRequestUtils.calculateAndAssignWorkingHours( + // startTime: requestDetailProvider.activityMaintenanceHelperModel!.startTime, + // endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime, + // workingHoursController: _workingHoursController, + // updateModel: (hours) { + // requestDetailProvider.activityMaintenanceHelperModel?.workingHour = hours; + // }, + // ); + // } + // }); + // }, + // ).expanded, + // ], + // ), + 8.height, + if (totalWorkingHours > 0.0) ...[ + Container( + height: 56.toScreenHeight, + padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), + alignment: Alignment.centerLeft, + decoration: BoxDecoration( + color: context.isDark ? AppColor.neutral40 : AppColor.background(context), + borderRadius: BorderRadius.circular(10), + boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Total Working Time", + style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), + ), + Text( + " ${ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round())}", + style: Theme.of(context).textTheme.bodyMedium, + ), + ], + ), ), + 8.height, + ], + // if (totalWorkingHours > 0.0) ...[ + // AppTextFormField( + // labelText: context.translation.workingHours, + // backgroundColor: AppColor.neutral80, + // controller: _workingHoursController, + // suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), + // initialValue: requestDetailProvider.activityMaintenanceHelperModel?.workingHour != null ? requestDetailProvider.activityMaintenanceHelperModel?.workingHour.toString() : '', + // textAlign: TextAlign.center, + // labelStyle: AppTextStyles.textFieldLabelStyle, + // enable: false, + // showShadow: false, + // style: Theme.of(context).textTheme.titleMedium, + // ), + // 8.height, + // ], + AppTextFormField( + labelText: context.translation.travelingHours, + controller: _travellingHoursController, + backgroundColor: AppColor.neutral100, + showShadow: false, + labelStyle: AppTextStyles.textFieldLabelStyle, + suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.travelHours?.toString(), + textInputType: TextInputType.number, + onChange: (value) { + requestDetailProvider.activityMaintenanceHelperModel?.travelHours = num.parse(value); // int.tryParse(value); + }, + // contentPadding: EdgeInsets.symmetric(vertical: 18.toScreenHeight, horizontal: 16.toScreenWidth), + onSaved: (value) { + requestDetailProvider.activityMaintenanceHelperModel?.travelHours = value as num?; + }, + ), + 16.height, + repairLocationWidget(context, requestDetailProvider), + 16.height, + AppTextFormField( + labelText: context.translation.assignedEmployee, + backgroundColor: AppColor.neutral80, + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.assignedEmployee?.userName, + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + showShadow: false, + enable: false, + style: Theme.of(context).textTheme.titleMedium, ), 8.height, + AppTextFormField( + initialValue: requestDetailProvider.activityMaintenanceHelperModel?.technicalComment, + labelText: context.translation.technicalComment, + backgroundColor: AppColor.neutral100, + showShadow: false, + labelStyle: AppTextStyles.textFieldLabelStyle, + alignLabelWithHint: true, + textInputType: TextInputType.multiline, + onChange: (value) { + requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value; + }, + onSaved: (value) { + requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value; + }, + ), ], - // if (totalWorkingHours > 0.0) ...[ - // AppTextFormField( - // labelText: context.translation.workingHours, - // backgroundColor: AppColor.neutral80, - // controller: _workingHoursController, - // suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), - // initialValue: requestDetailProvider.activityMaintenanceHelperModel?.workingHour != null ? requestDetailProvider.activityMaintenanceHelperModel?.workingHour.toString() : '', - // textAlign: TextAlign.center, - // labelStyle: AppTextStyles.textFieldLabelStyle, - // enable: false, - // showShadow: false, - // style: Theme.of(context).textTheme.titleMedium, - // ), - // 8.height, - // ], - AppTextFormField( - labelText: context.translation.travelingHours, - controller: _travellingHoursController, - backgroundColor: AppColor.neutral100, - showShadow: false, - labelStyle: AppTextStyles.textFieldLabelStyle, - suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), - initialValue: requestDetailProvider.activityMaintenanceHelperModel?.travelHours?.toString(), - textInputType: TextInputType.number, - onChange: (value) { - requestDetailProvider.activityMaintenanceHelperModel?.travelHours = num.parse(value) ;// int.tryParse(value); - }, - // contentPadding: EdgeInsets.symmetric(vertical: 18.toScreenHeight, horizontal: 16.toScreenWidth), - onSaved: (value) { - requestDetailProvider.activityMaintenanceHelperModel?.travelHours = value as num?; - }, - ), - 16.height, - repairLocationWidget(context, requestDetailProvider), - 16.height, - AppTextFormField( - labelText: context.translation.assignedEmployee, - backgroundColor: AppColor.neutral80, - initialValue: requestDetailProvider.activityMaintenanceHelperModel?.assignedEmployee?.userName, - textAlign: TextAlign.center, - labelStyle: AppTextStyles.textFieldLabelStyle, - showShadow: false, - enable: false, - style: Theme.of(context).textTheme.titleMedium, - ), - 8.height, - AppTextFormField( - initialValue: requestDetailProvider.activityMaintenanceHelperModel?.technicalComment, - labelText: context.translation.technicalComment, - backgroundColor: AppColor.neutral100, - showShadow: false, - labelStyle: AppTextStyles.textFieldLabelStyle, - alignLabelWithHint: true, - textInputType: TextInputType.multiline, - onChange: (value) { - requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value; - }, - onSaved: (value) { - requestDetailProvider.activityMaintenanceHelperModel?.technicalComment = value; - }, - ), - ], - ), - ).toShadowContainer(context).paddingOnly(start: 13, end: 14, top: 12), - const AssistantEmployeeCard().toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16)).paddingOnly(start: 13, end: 14, top: 12), - 100.height, - ], + ), + ).toShadowContainer(context).paddingOnly(start: 13, end: 14, top: 12), + const AssistantEmployeeCard().toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16)).paddingOnly(start: 13, end: 14, top: 12), + 100.height, + ], + ), ), ); }); diff --git a/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart b/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart index e60383bb..9da93430 100644 --- a/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart +++ b/lib/service_request_latest/views/forms/maintenance_request/maintenance_request_main.dart @@ -18,7 +18,7 @@ import 'package:test_sa/service_request_latest/views/forms/maintenance_request/c import 'package:test_sa/service_request_latest/views/forms/maintenance_request/components/internal_request.dart'; class MaintenanceRequestForm extends StatefulWidget { - const MaintenanceRequestForm({Key? key}) : super(key: key); + MaintenanceRequestForm({Key? key}) : super(key: key); @override _MaintenanceRequestFormState createState() => _MaintenanceRequestFormState(); @@ -47,9 +47,16 @@ class _MaintenanceRequestFormState extends State with Si Widget build(BuildContext context) { return Consumer(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) { bool isUpdate = requestDetailProvider.activityMaintenanceHelperModel?.id != 0; - return Scaffold( + return Scaffold( backgroundColor: AppColor.neutral110, - appBar: const DefaultAppBar(title: "CM Activity"), + appBar: DefaultAppBar( + title: "CM Activity", + onWillPopScope: requestDetailProvider.isReadOnlyRequest + ? null + : () { + save(requestDetailProvider); + }, + ), body: Stack( children: [ DefaultTabController( @@ -92,53 +99,55 @@ class _MaintenanceRequestFormState extends State with Si ], ), ), - FooterActionButton.footerContainer( - child: AppFilledButton( - label: requestDetailProvider.activityMaintenanceHelperModel?.id != 0 ? context.translation.update : context.translation.addActivity, // Use the dynamic label - buttonColor: AppColor.primary10, - onPressed: () async { - //TODO add this as dropdown not added in design yet Bhaa need to confirm with hussain then. - // requestDetailProvider.activityMaintenanceHelperModel?.lastSituationId = 282; - - if (validate(model: requestDetailProvider.activityMaintenanceHelperModel!)) { - requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers = requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers ?? []; - requestDetailProvider.activityMaintenanceHelperModel?.timerModelList?.forEach((timer) { - int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds; - requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers?.add( - ActivityMaintenanceTimers( - id: 0, - startTime: timer.startAt!.toIso8601String(), // Handle potential null - endTime: timer.endAt?.toIso8601String(), // Handle potential null - workingHours: ((durationInSecond) / 60 / 60), - ), - ); - }); - showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); - int status = -1; - if (requestDetailProvider.activityMaintenanceHelperModel?.id == 0) { - status = await requestDetailProvider.createActivityMaintenanceRequest(); - } else { - status = await requestDetailProvider.updateActivityMaintenance(); - } - if (status == 200) { - requestDetailProvider.getWorkOrderById(id: requestDetailProvider.currentWorkOrder!.data!.requestId!); - Navigator.pop(context); - Navigator.pop(context); - } else { - Navigator.pop(context); - } - } - - // Handle button press - }, + if (!requestDetailProvider.isReadOnlyRequest) + FooterActionButton.footerContainer( + child: AppFilledButton( + label: requestDetailProvider.activityMaintenanceHelperModel?.id != 0 ? context.translation.update : context.translation.addActivity, // Use the dynamic label + buttonColor: AppColor.primary10, + onPressed: () async { + save(requestDetailProvider); + }, + ), ), - ), ], ), - ); + ).handlePopScope(cxt: context, showPopUp: !requestDetailProvider.isReadOnlyRequest, onSave: () { + save(requestDetailProvider); + }); }); } + void save(ServiceRequestDetailProvider requestDetailProvider) async { + if (validate(model: requestDetailProvider.activityMaintenanceHelperModel!)) { + requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers = requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers ?? []; + requestDetailProvider.activityMaintenanceHelperModel?.timerModelList?.forEach((timer) { + int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds; + requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimers?.add( + ActivityMaintenanceTimers( + id: 0, + startTime: timer.startAt!.toIso8601String(), // Handle potential null + endTime: timer.endAt?.toIso8601String(), // Handle potential null + workingHours: ((durationInSecond) / 60 / 60), + ), + ); + }); + showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); + int status = -1; + if (requestDetailProvider.activityMaintenanceHelperModel?.id == 0) { + status = await requestDetailProvider.createActivityMaintenanceRequest(); + } else { + status = await requestDetailProvider.updateActivityMaintenance(); + } + if (status == 200) { + requestDetailProvider.getWorkOrderById(id: requestDetailProvider.currentWorkOrder!.data!.requestId!); + Navigator.pop(context); + Navigator.pop(context); + } else { + Navigator.pop(context); + } + } + } + bool validate({required ActivityMaintenanceHelperModel model}) { if (model.activityStatus == null) { Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.activityStatus}"); diff --git a/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart b/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart index 3df20c4c..8b1454a6 100644 --- a/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart +++ b/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/all_requests_provider.dart'; import 'package:test_sa/controllers/providers/api/parts_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; @@ -11,6 +12,7 @@ import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/helper_data_models/spare_part/activity_spare_part_model.dart'; import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/size_config.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.dart'; @@ -19,6 +21,7 @@ import 'package:test_sa/service_request_latest/service_request_detail_provider.d import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/service_request_latest/views/components/bottom_sheets/service_request_bottomsheet.dart'; import 'package:test_sa/views/widgets/images/new_multi_image_picker.dart'; +import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; import '../../../../../../models/service_request/spare_parts.dart'; import '../../../../../../new_views/common_widgets/app_text_form_field.dart'; @@ -80,7 +83,7 @@ class _SparePartRequestState extends State with TickerProvider _isLoading = true; _files = _requestDetailProvider?.sparePartHelperModel?.sparePartAttachments?.map((e) => MultiFilesPickerModel(e.id!, File(e.name!))).toList() ?? []; setState(() {}); - _spareParts = await _partsProvider!.getPartsList(assetId: _requestDetailProvider?.currentWorkOrder?.data?.asset?.id); + _spareParts = await _partsProvider!.getPartsListByDisplayName(assetId: _requestDetailProvider?.currentWorkOrder?.data?.asset?.id); _isLoading = false; setState(() {}); @@ -119,6 +122,7 @@ class _SparePartRequestState extends State with TickerProvider key: _scaffoldKey, appBar: DefaultAppBar(title: context.translation.sparePartRequest), body: Consumer(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) { + print('data i got is ${requestDetailProvider.sparePartHelperModel?.sparePart?.toJson()}'); return SafeArea( child: Form( key: _formKey, @@ -148,14 +152,14 @@ class _SparePartRequestState extends State with TickerProvider 12.height, SingleItemDropDownMenu( context: context, - title: context.translation.partNo, + title: context.translation.part, staticData: _spareParts, showShadow: false, showAsBottomSheet: true, loading: _isLoading, initialValue: requestDetailProvider.sparePartHelperModel?.sparePart, backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90, - onSelect: (part) { + onSelect: (part) async { if (part != null) { requestDetailProvider.sparePartHelperModel?.sparePart = part; _oracleNoController.text = part.oracleCode ?? ''; @@ -163,6 +167,36 @@ class _SparePartRequestState extends State with TickerProvider } }, ), + + if(requestDetailProvider.sparePartHelperModel?.sparePart?.id!=null)...[ + 12.height, + SizedBox( + height: 30.toScreenHeight, + child: Text('View Parts Availability',style:TextStyle( + fontSize: 12.toScreenWidth, + fontWeight: FontWeight.w500, + fontStyle: FontStyle.normal, + color:AppColor.primary10 , + decorationColor: AppColor.primary10, + decoration: TextDecoration.underline, + )).onPress( + () async { + requestDetailProvider.getStoreAvailabilityById(partId: requestDetailProvider.sparePartHelperModel?.sparePart?.id); + showModalBottomSheet( + context: context, + isScrollControlled: true, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + clipBehavior: Clip.antiAliasWithSaveLayer, + builder: (BuildContext context) => PartDetailBottomSheetSheet(), + ); + }, + ), + ), + ], 12.height, AppTextFormField( controller: _partQtyController, @@ -245,7 +279,7 @@ class _SparePartRequestState extends State with TickerProvider controller: _descriptionController, showSpeechToText: true, backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90, - labelText: context.translation.description, + labelText: "Engineer Comment", alignLabelWithHint: true, showWithoutDecoration: true, textInputType: TextInputType.multiline, @@ -309,4 +343,58 @@ class _SparePartRequestState extends State with TickerProvider }), ); } + +} + + +class PartDetailBottomSheetSheet extends StatelessWidget { + + PartDetailBottomSheetSheet( {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return SizedBox( + height: SizeConfig.screenHeight!/2.2, + width: SizeConfig.screenWidth, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 8.height, + 'Parts Availability'.heading6(context).paddingOnly(top: 12,start: 12), + Consumer( + builder: (context, requestDetailProvider,child) { + return requestDetailProvider.isLoading + ? const CircularProgressIndicator(color: AppColor.primary10).center + : requestDetailProvider.storeAvailability.isEmpty + ? const NoDataFound().center + : ListView.separated( + padding: const EdgeInsets.all(16), + itemCount: requestDetailProvider.storeAvailability.length, + separatorBuilder: (czt, index) => 12.height, + itemBuilder: (context, index) { + StoreAvailability model = requestDetailProvider.storeAvailability[index]; + return partAvailableQuantityCard(context: context,model:model); + }, + ); + } + ).expanded, + ], + ), + ); + } + Widget partAvailableQuantityCard({required StoreAvailability model,required BuildContext context }){ + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 'Site Name: ${model.siteName??''}'.bodyText2(context).custom(color: AppColor.neutral120), + 8.height, + 'Store Name: ${model.storeName??''}'.bodyText2(context).custom(color: AppColor.neutral120), + 8.height, + 'Available Quantity: ${model.availablityQty??''}'.bodyText2(context).custom(color: AppColor.neutral120), + 8.height, + ] + ).toShadowContainer(context, padding: 12, showShadow: false,backgroundColor: AppColor.neutral110); + } } diff --git a/lib/service_request_latest/views/service_request_detail_main_view.dart b/lib/service_request_latest/views/service_request_detail_main_view.dart index 13e6e432..4ea8d260 100644 --- a/lib/service_request_latest/views/service_request_detail_main_view.dart +++ b/lib/service_request_latest/views/service_request_detail_main_view.dart @@ -128,10 +128,10 @@ class _ServiceRequestDetailMainState extends State { ), ), 12.height, - const TabBarView( + TabBarView( children: [ ServiceRequestDetailView(), - HistoryLogView(), + const HistoryLogView(), ], ).expanded, ], diff --git a/lib/views/pages/device_transfer/create__asset_transfer_request.dart b/lib/views/pages/device_transfer/create__asset_transfer_request.dart new file mode 100644 index 00000000..0ffd8dfe --- /dev/null +++ b/lib/views/pages/device_transfer/create__asset_transfer_request.dart @@ -0,0 +1,345 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/asset_transfer_provider.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/device/asset.dart'; +import 'package:test_sa/models/device/asset_transfer.dart'; +import 'package:test_sa/models/device/asset_transfer_attachment.dart'; +import 'package:test_sa/models/new_models/department.dart'; +import 'package:test_sa/models/new_models/floor.dart'; +import 'package:test_sa/models/service_request/pending_service_request_model.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; +import 'package:test_sa/providers/ppm_service_provider.dart'; +import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart'; +import 'package:test_sa/views/pages/user/requests/pending_requests_screen.dart'; +import 'package:test_sa/views/widgets/bottom_sheets/pending_request_bottom_sheet.dart'; +import 'package:test_sa/views/widgets/equipment/asset_picker.dart'; +import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; +import '../../../models/new_models/building.dart'; +import '../../../models/new_models/site.dart'; +import '../../../new_views/common_widgets/app_filled_button.dart'; +import '../../../new_views/common_widgets/default_app_bar.dart'; +import '../../../new_views/common_widgets/single_item_drop_down_menu.dart'; +import '../../../providers/gas_request_providers/site_provider.dart'; +import '../../../providers/loading_list_notifier.dart'; + +class CreateAssetTransferRequest extends StatefulWidget { + static const String id = "/request-device-transfer"; + + const CreateAssetTransferRequest({Key? key}) : super(key: key); + + @override + State createState() => _CreateAssetTransferRequestState(); +} + +class _CreateAssetTransferRequestState extends State { + late AssetTransferProvider _deviceTransferProvider; + final TextEditingController _requestedQuantityController = TextEditingController(); + final AssetTransfer _transferModel = AssetTransfer(id: 0); + final GlobalKey _formKey = GlobalKey(); + final GlobalKey _scaffoldKey = GlobalKey(); + final TextEditingController _receiverNameController = TextEditingController(), _commentsController = TextEditingController(); + final Asset _assetDestination = Asset(); + Asset? _pickedAsset; + final List _deviceImages = []; + PendingAssetServiceRequest? pendingAssetServiceRequest; + + @override + void setState(VoidCallback fn) { + if (mounted) super.setState(() {}); + } + + bool checkPendingRequest = false; + + void showPendingRequests() { + Navigator.of(context).push(MaterialPageRoute(builder: (_) => PendingServiceRequestScreen(pendingAssetServiceRequest!))); + } + + void _onSubmit() async { + _transferModel.assetId = _pickedAsset?.id; + _transferModel.destSiteId = _assetDestination.site?.id; + _transferModel.destBuildingId = _assetDestination.building?.id; + _transferModel.destFloorId = _assetDestination.floor?.id; + _transferModel.destDepartmentId = _assetDestination.department?.id; + _transferModel.destRoomId = _assetDestination.room?.id; + + if (!_formKey.currentState!.validate() || !(await _transferModel.validate(context))) { + return; + } + _formKey.currentState!.save(); + List attachement = []; + for (var item in _deviceImages) { + attachement.add(AssetTransferAttachment(id: 0, attachmentName: "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}")); + } + _transferModel.attachments = attachement; + + + await _deviceTransferProvider.createRequest( + context: context, + model: _transferModel, + ); + } + + @override + void initState() { + WidgetsBinding.instance.addPostFrameCallback((_) async { + Provider.of(context, listen: false).getDate(); + }); + super.initState(); + } + + + @override + void dispose() { + _requestedQuantityController.dispose(); + _deviceTransferProvider.reset(); + _receiverNameController.dispose(); + _commentsController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + _deviceTransferProvider = Provider.of(context, listen: false); + return Scaffold( + key: _scaffoldKey, + appBar: DefaultAppBar( + title: context.translation.createAssetTransferRequest, + titleStyle: AppTextStyles.heading3.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ), + body: Form( + key: _formKey, + child: SafeArea( + child: Column( + children: [ + SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AssetPicker( + device: _pickedAsset, + showLoading: false, + borderColor: AppColor.black20, + backgroundColor: AppColor.white936, + onPick: (asset) async { + _pickedAsset = asset; + // await checkAssetForPendingServiceRequest(asset.id!.toInt()); + // if (_pickedAsset != null && pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) { + // showPendingRequestBottomSheet(); + // } + setState(() {}); + }), + // if (pendingAssetServiceRequest != null && pendingAssetServiceRequest!.details!.isNotEmpty) ...[ + // 8.height, + // Row( + // children: [ + // const Icon(Icons.warning, color: Color(0xffEE404C), size: 14), + // 8.width, + // Text( + // "This asset already have ${pendingAssetServiceRequest!.details!.length} request pending", + // style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500, color: Color(0xff7D859A), decoration: TextDecoration.underline), + // ).expanded, + // ], + // ).onPress(() { + // showPendingRequests(); + // }), + // ], + 21.height, + requestTypeWidget(context), + 12.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SingleItemDropDownMenu( + context: context, + title: context.translation.site, + initialValue: _assetDestination.site, + showShadow: false, + backgroundColor: AppColor.neutral100, + showAsBottomSheet: true, + onSelect: (value) { + _assetDestination.site = value; + _assetDestination.building = null; + _assetDestination.floor = null; + _assetDestination.department = null; + setState(() {}); + }, + ).expanded, + 8.width, + SingleItemDropDownMenu( + context: context, + title: context.translation.building, + initialValue: _assetDestination.building, + showShadow: false, + showAsBottomSheet: true, + backgroundColor: AppColor.neutral100, + enabled: _assetDestination.site?.buildings?.isNotEmpty ?? false, + staticData: _assetDestination.site?.buildings ?? [], + onSelect: (value) { + _assetDestination.building = value; + _assetDestination.floor = null; + _assetDestination.department = null; + setState(() {}); + }, + ).expanded, + ], + ), + 8.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SingleItemDropDownMenu( + context: context, + title: context.translation.floor, + showShadow: false, + showAsBottomSheet: true, + initialValue: _assetDestination.floor, + backgroundColor: AppColor.neutral100, + enabled: _assetDestination.building?.floors?.isNotEmpty ?? false, + staticData: _assetDestination.building?.floors ?? [], + onSelect: (value) { + _assetDestination.floor = value; + _assetDestination.department = null; + setState(() {}); + }, + ).expanded, + 8.width, + SingleItemDropDownMenu( + context: context, + title: context.translation.department, + showShadow: false, + showAsBottomSheet: true, + initialValue: _assetDestination.department, + backgroundColor: AppColor.neutral100, + enabled: _assetDestination.floor?.departments?.isNotEmpty ?? false, + staticData: _assetDestination.floor?.departments ?? [], + onSelect: (value) { + _assetDestination.department = value; + _assetDestination.room = null; + setState(() {}); + }, + ).expanded, + ], + ), + 8.height, + AppTextFormField( + controller: _commentsController, + backgroundColor: AppColor.neutral100, + labelText: context.translation.callComments, + labelStyle: AppTextStyles.textFieldLabelStyle, + alignLabelWithHint: true, + textInputType: TextInputType.multiline, + showShadow: false, + onSaved: (text) { + _transferModel.comment = text; + }, + ), + 8.height, + 23.height, + MultiFilesPicker( + label: context.translation.attachImage, + files: _deviceImages, + buttonColor: AppColor.black10, + onlyImages: true, + buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), + ), + // 100.height, + ], + ).toShadowContainer(context).paddingOnly(top: 20, start: 16, end: 16), + ).expanded, + FooterActionButton.footerContainer( + child: AppFilledButton(buttonColor: AppColor.primary10, label: context.translation.submitRequest, maxWidth: true, onPressed: _onSubmit), + ), + ], + ), + ), + ), + ); + } + + Future checkAssetForPendingServiceRequest(int assetId) async { + checkPendingRequest = true; + setState(() {}); + + pendingAssetServiceRequest = await _deviceTransferProvider.checkAssetPendingRequest(assetId); + await Future.delayed(const Duration(milliseconds: 250)); + + checkPendingRequest = false; + setState(() {}); + } + + void showPendingRequestBottomSheet() async { + bool view = (await showModalBottomSheet( + context: context, + isDismissible: false, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + clipBehavior: Clip.antiAliasWithSaveLayer, + builder: (BuildContext context) => PendingRequestBottomSheet(pendingAssetServiceRequest!, _pickedAsset!), + )) as bool; + if (view) { + showPendingRequests(); + } + } + + Widget requestTypeWidget(BuildContext context) { + return Consumer(builder: (cxt, snapshot, _) { + try { + _transferModel.transferType ??= snapshot.items.first; + } catch (ex) { + print("snapshot.items:${snapshot.items.length}"); + } + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + context.translation.requestType.bodyText(context).custom(color: AppColor.white936), + 8.height, + Wrap( + runSpacing: 8, + spacing: 8, + children: [ + for (var element in snapshot.items) + Row( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: 24, + height: 24, + child: Radio( + value: element, + activeColor: AppColor.primary10, + fillColor: WidgetStateColor.resolveWith((states) { + if (states.contains(WidgetState.selected)) { + return AppColor.primary10; // Thumb color when selected + } + return Colors.grey; // Thumb color when unselected (grey) + }), + groupValue: _transferModel.transferType, + onChanged: (state) { + _transferModel.transferType = element; + setState(() {}); + // }); + }), + ), + 8.width, + Text(element.name ?? '', style: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral120)), + ], + ) + ], + ).toShimmer(isShow: snapshot.loading), + ], + ); + }); + } +} diff --git a/lib/views/pages/device_transfer/device_transfer_details.dart b/lib/views/pages/device_transfer/device_transfer_details.dart index 1815d04c..68b5056a 100644 --- a/lib/views/pages/device_transfer/device_transfer_details.dart +++ b/lib/views/pages/device_transfer/device_transfer_details.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/asset_transfer_provider.dart'; @@ -8,6 +10,7 @@ import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/device/asset_transfer.dart'; import 'package:test_sa/views/pages/device_transfer/update_device_transfer.dart'; +import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; @@ -31,6 +34,7 @@ class _DeviceTransferDetailsState extends State { AssetTransfer? _model; final bool _isLoading = false; final GlobalKey _formKey = GlobalKey(); + List _attachments = []; final GlobalKey _scaffoldKey = GlobalKey(); @override @@ -41,6 +45,7 @@ class _DeviceTransferDetailsState extends State { @override Widget build(BuildContext context) { _userProvider ??= Provider.of(context); + return Scaffold( appBar: DefaultAppBar(title: context.translation.deviceTransferDetails), key: _scaffoldKey, @@ -52,6 +57,7 @@ class _DeviceTransferDetailsState extends State { return const ALoading(); } else { _model = snapshot.data as AssetTransfer?; + _attachments = _model?.attachments?.map((e) => File(e.attachmentName ?? '')).toList() ?? []; return Form( key: _formKey, @@ -89,6 +95,8 @@ class _DeviceTransferDetailsState extends State { const Divider().defaultStyle(context), 8.height, _buildTextWidget(_model!.comment!), + + ] ], ), @@ -177,6 +185,27 @@ class _DeviceTransferDetailsState extends State { return widget.toShadowContainer(context).paddingOnly(top: 14, start: 14, end: 14); } + Widget attachmentWidget(){ + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 8.height, + if (_attachments.isNotEmpty) ...[ + const Divider().defaultStyle(context), + context.translation.attachments.bodyText(context), + 8.height, + MultiFilesPicker( + label: context.translation.attachments, + files: _attachments, + enabled: false, + onlyImages: false, + ), + 12.height, + ], + ], + ); + } + _buildTextWidget(String text) { return text.bodyText(context); } @@ -224,6 +253,8 @@ class _DeviceTransferDetailsState extends State { const Divider().defaultStyle(context), 8.height, _buildTextWidget(comment), + attachmentWidget(), + ] ], ).toShadowContainer(context); @@ -237,4 +268,6 @@ class _DeviceTransferDetailsState extends State { } } + + } diff --git a/lib/views/pages/device_transfer/request_device_transfer.dart b/lib/views/pages/device_transfer/request_device_transfer.dart deleted file mode 100644 index ea7ccb03..00000000 --- a/lib/views/pages/device_transfer/request_device_transfer.dart +++ /dev/null @@ -1,211 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:test_sa/controllers/providers/api/asset_transfer_provider.dart'; -import 'package:test_sa/controllers/providers/api/status_drop_down/employee/nurse_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/context_extension.dart'; -import 'package:test_sa/extensions/int_extensions.dart'; -import 'package:test_sa/extensions/text_extensions.dart'; -import 'package:test_sa/extensions/widget_extensions.dart'; -import 'package:test_sa/models/device/asset.dart'; -import 'package:test_sa/models/device/asset_transfer.dart'; -import 'package:test_sa/models/employee.dart'; -import 'package:test_sa/models/new_models/department.dart'; -import 'package:test_sa/models/new_models/floor.dart'; -import 'package:test_sa/models/new_models/room_model.dart'; -import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; -import 'package:test_sa/views/widgets/status/employee/nurse_menu.dart'; - -import '../../../models/new_models/building.dart'; -import '../../../models/new_models/site.dart'; -import '../../../new_views/common_widgets/app_filled_button.dart'; -import '../../../new_views/common_widgets/default_app_bar.dart'; -import '../../../new_views/common_widgets/single_item_drop_down_menu.dart'; -import '../../../providers/gas_request_providers/site_provider.dart'; -import '../../../providers/loading_list_notifier.dart'; -import '../../widgets/equipment/pick_asset.dart'; - -class RequestDeviceTransfer extends StatefulWidget { - static const String id = "/request-device-transfer"; - - const RequestDeviceTransfer({Key? key}) : super(key: key); - - @override - State createState() => _RequestDeviceTransferState(); -} - -class _RequestDeviceTransferState extends State { - UserProvider? _userProvider; - SettingProvider? _settingProvider; - late AssetTransferProvider _deviceTransferProvider; - final TextEditingController _requestedQuantityController = TextEditingController(); - final AssetTransfer _transferModel = AssetTransfer(); - final GlobalKey _formKey = GlobalKey(); - final GlobalKey _scaffoldKey = GlobalKey(); - final TextEditingController _receiverNameController = TextEditingController(), _commentsController = TextEditingController(); - final Asset _assetDestination = Asset(); - Asset? _pickedAsset; - Employee? receiverEndUser; - Employee? _selectedNurse; - - @override - void setState(VoidCallback fn) { - if (mounted) super.setState(() {}); - } - - void _onSubmit() async { - _transferModel.assetId = _pickedAsset?.id; - _transferModel.destSiteId = _assetDestination.site?.id; - _transferModel.destBuildingId = _assetDestination.building?.id; - _transferModel.destFloorId = _assetDestination.floor?.id; - _transferModel.destDepartmentId = _assetDestination.department?.id; - _transferModel.destRoomId = _assetDestination.room?.id; - _transferModel.receiverEndUserId = _selectedNurse?.id; - if (!_formKey.currentState!.validate() || !(await _transferModel.validate(context))) { - return; - } - _formKey.currentState!.save(); - await _deviceTransferProvider.createRequest(context: context, assetDestination: _transferModel, asset: _pickedAsset!); - } - - @override - void dispose() { - _requestedQuantityController.dispose(); - _deviceTransferProvider.reset(); - _receiverNameController.dispose(); - _commentsController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - _userProvider = Provider.of(context, listen: false); - _settingProvider = Provider.of(context, listen: false); - _deviceTransferProvider = Provider.of(context, listen: false); - // _selectedNurse ??= Employee(id: _userProvider.user.userID, name: _userProvider.user.username); - - return Scaffold( - key: _scaffoldKey, - appBar: DefaultAppBar(title: context.translation.newTransferRequest), - body: Form( - key: _formKey, - child: SafeArea( - child: Column( - children: [ - SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - 16.height, - PickAsset( - device: _pickedAsset, - onPickAsset: (asset) { - _pickedAsset = asset; - setState(() {}); - }, - ), - 16.height, - context.translation.receiverDetails.heading5(context), - 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.destinationSite, - initialValue: _assetDestination.site, - onSelect: (value) { - _assetDestination.site = value; - _assetDestination.building = null; - _assetDestination.floor = null; - _assetDestination.department = null; - _selectedNurse = null; - Provider.of(context, listen: false).siteId = value!.id!.toInt(); - Provider.of(context, listen: false).getData(); - setState(() {}); - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.building, - initialValue: _assetDestination.building, - enabled: _assetDestination.site?.buildings?.isNotEmpty ?? false, - staticData: _assetDestination.site?.buildings ?? [], - onSelect: (value) { - _assetDestination.building = value; - _assetDestination.floor = null; - _assetDestination.department = null; - setState(() {}); - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.floor, - initialValue: _assetDestination.floor, - enabled: _assetDestination.building?.floors?.isNotEmpty ?? false, - staticData: _assetDestination.building?.floors ?? [], - onSelect: (value) { - _assetDestination.floor = value; - _assetDestination.department = null; - setState(() {}); - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.department, - initialValue: _assetDestination.department, - enabled: _assetDestination.floor?.departments?.isNotEmpty ?? false, - staticData: _assetDestination.floor?.departments ?? [], - onSelect: (value) { - _assetDestination.department = value; - _assetDestination.room = null; - setState(() {}); - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.room, - initialValue: _assetDestination.room, - enabled: _assetDestination.department?.rooms?.isNotEmpty ?? false, - staticData: _assetDestination.department?.rooms ?? [], - onSelect: (value) { - _assetDestination.room = value; - setState(() {}); - }, - ), - 8.height, - NurseMenu( - title: context.translation.receiverName, - initialValue: _selectedNurse, - enable: _assetDestination.site != null, - onSelect: (employee) { - if (employee != null) { - _selectedNurse = employee; - setState(() {}); - } - }, - ), - 16.height, - context.translation.comments.heading5(context), - 8.height, - AppTextFormField( - controller: _commentsController, - labelText: context.translation.comments, - onSaved: (text) { - _transferModel.comment = text; - }, - ), - 100.height, - ], - ), - ).expanded, - AppFilledButton(label: context.translation.submitRequest, maxWidth: true, onPressed: _onSubmit) - ], - ).paddingOnly(start: 16, end: 16, bottom: 24), - ), - ), - ); - } -} diff --git a/lib/views/pages/device_transfer/update_device_transfer.dart b/lib/views/pages/device_transfer/update_device_transfer.dart index 8a3ffcf9..7721a406 100644 --- a/lib/views/pages/device_transfer/update_device_transfer.dart +++ b/lib/views/pages/device_transfer/update_device_transfer.dart @@ -1,33 +1,366 @@ +//older code. +// import 'dart:convert'; +// import 'dart:io'; +// +// 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/providers/api/asset_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/context_extension.dart'; +// import 'package:test_sa/extensions/int_extensions.dart'; +// import 'package:test_sa/extensions/string_extensions.dart'; +// import 'package:test_sa/extensions/widget_extensions.dart'; +// import 'package:test_sa/models/device/asset_transfer.dart'; +// import 'package:test_sa/models/device/asset_transfer_attachment.dart'; +// import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +// import 'package:test_sa/providers/asset_transfer/asset_transfer_status_provider.dart'; +// import 'package:test_sa/views/app_style/sizing.dart'; +// import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; +// import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +// +// import '../../../extensions/text_extensions.dart'; +// import '../../../models/lookup.dart'; +// import '../../../models/ppm/ppm.dart'; +// import '../../../new_views/app_style/app_color.dart'; +// import '../../../new_views/common_widgets/app_text_form_field.dart'; +// import '../../../new_views/common_widgets/default_app_bar.dart'; +// import '../../../new_views/common_widgets/single_item_drop_down_menu.dart'; +// import '../../widgets/e_signature/e_signature.dart'; +// import '../../widgets/timer/app_timer.dart'; +// +// class UpdateDeviceTransfer extends StatefulWidget { +// final AssetTransfer model; +// final bool isSender; +// +// const UpdateDeviceTransfer({Key? key, required this.model, required this.isSender}) : super(key: key); +// +// @override +// State createState() => _UpdateDeviceTransferState(); +// } +// +// class _UpdateDeviceTransferState extends State { +// final bool _isLoading = false; +// bool _validate = false; +// late UserProvider _userProvider; +// late SettingProvider _settingProvider; +// Uint8List? _signature; +// late AssetTransferProvider _deviceTransferProvider; +// final TextEditingController _requestedQuantityController = TextEditingController(); +// final AssetTransfer _formModel = AssetTransfer(); +// final GlobalKey _formKey = GlobalKey(); +// final GlobalKey _scaffoldKey = GlobalKey(); +// +// List _files = []; +// +// _update() async { +// if (widget.isSender) { +// _formModel.senderVisitTimers?.add( +// VisitTimers( +// id: 0, +// startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(), +// endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(), +// workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60), +// ), +// ); +// } else { +// _formModel.receiverVisitTimers?.add( +// VisitTimers( +// id: 0, +// startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(), +// endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(), +// workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60), +// ), +// ); +// } +// +// if (_formModel.tbsTimer?.startAt == null) { +// await Fluttertoast.showToast(msg: "Working Hours Required"); +// return false; +// } +// if (_formModel.tbsTimer?.endAt == null || isTimerRunning) { +// await Fluttertoast.showToast(msg: "Please Stop The Timer"); +// return false; +// } +// _validate = true; +// if (!(_formKey.currentState!.validate())) { +// setState(() {}); +// return false; +// } +// _formKey.currentState!.save(); +// +// if (widget.isSender) { +// _formModel.senderAttachments = []; +// } else { +// _formModel.receiverAttachments = []; +// } +// +// try { +// for (var file in _files) { +// String attachmentName = file.path; +// if (attachmentName.contains("/")) { +// attachmentName = file.path.split("/").last; +// attachmentName = "$attachmentName|${base64Encode(file.readAsBytesSync())}"; +// } +// +// if (widget.isSender) { +// _formModel.senderAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName)); +// } else { +// _formModel.receiverAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName)); +// } +// } +// } catch (error) { +// print(error); +// } +// await _deviceTransferProvider.updateRequest(context, assetTransfer: _formModel, isSender: widget.isSender); +// } +// +// @override +// void initState() { +// _formModel.fromDetails(widget.model); +// +// if (widget.isSender) { +// _files = widget.model.senderAttachments?.map((e) => File(e.attachmentName!)).toList() ?? []; +// } else { +// _files = widget.model.receiverAttachments?.map((e) => File(e.attachmentName!)).toList() ?? []; +// } +// +// super.initState(); +// } +// +// @override +// void dispose() { +// _requestedQuantityController.dispose(); +// super.dispose(); +// } +// +// bool isTimerRunning = false; +// +// @override +// Widget build(BuildContext context) { +// _userProvider = Provider.of(context); +// _settingProvider = Provider.of(context); +// _deviceTransferProvider = Provider.of(context, listen: false); +// +// double totalWorkingHours = widget.isSender +// ? (widget.model.senderVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0) +// : (widget.model.receiverVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0); +// +// bool isTimerEnable = widget.isSender +// ? (!(_formModel.senderMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.senderMachineStatusName?.toLowerCase().contains("complete") ?? false)) +// : (!(_formModel.receiverMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.receiverMachineStatusName?.toLowerCase().contains("complete") ?? false)); +// +// return Scaffold( +// appBar: DefaultAppBar(title: context.translation.updateRequest), +// key: _scaffoldKey, +// body: SafeArea( +// child: LoadingManager( +// isLoading: _isLoading, +// isFailedLoading: false, +// stateCode: 200, +// onRefresh: () async {}, +// child: Form( +// key: _formKey, +// child: Column( +// children: [ +// SingleChildScrollView( +// padding: EdgeInsets.all(12 * AppStyle.getScaleFactor(context)), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.stretch, +// children: [ +// _buildCard(), +// 8.height, +// AppTextFormField( +// initialValue: widget.isSender ? _formModel.senderTravelingHours ?? "" : _formModel.receiverTravelingHours ?? "", +// labelText: context.translation.travelingHours, +// onChange: (text) { +// widget.isSender ? _formModel.senderTravelingHours = text : _formModel.receiverTravelingHours = text; +// }, +// onSaved: (value) { +// widget.isSender ? _formModel.senderTravelingHours = value : _formModel.receiverTravelingHours = value; +// //_formModel?.workingHours = double.tryParse(value); +// // _formModel.travelingHours = value; +// }, +// textInputType: TextInputType.number, +// //validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only", +// ), +// 8.height, +// if (totalWorkingHours > 0.0) ...[ +// Container( +// height: 50.toScreenHeight, +// padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), +// alignment: Alignment.centerLeft, +// decoration: BoxDecoration( +// color: context.isDark ? AppColor.neutral40 : AppColor.background(context), +// borderRadius: BorderRadius.circular(10), +// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], +// ), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// Text( +// "Total Working Time", +// style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), +// ), +// Text( +// " ${formatDuration(totalWorkingHours.round())}", +// style: Theme.of(context).textTheme.bodyLarge, +// ), +// ], +// ), +// ), +// 8.height, +// ], +// AppTimer( +// label: context.translation.workingHours, +// timer: _formModel.tbsTimer, +// enabled: isTimerEnable, +// // enabled: widget.isSender ? _formModel.senderEndDate == null : (_formModel?.receiverMachineStatusName?.toLowerCase()?.contains("close") ?? false), +// timerProgress: (isRunning) { +// isTimerRunning = isRunning; +// }, +// onChange: (timer) async { +// _formModel.tbsTimer = timer; +// return true; +// }, +// ), +// 8.height, +// Consumer(builder: (context, snapshot, _) { +// return SingleItemDropDownMenu( +// context: context, +// title: widget.isSender ? "Status Sender" : "Status Receiver", //,context.translation.reportStatus, +// initialValue: +// snapshot.items.firstWhere((element) => element.name == (widget.isSender ? _formModel.senderMachineStatusName : _formModel.receiverMachineStatusName), orElse: null), +// onSelect: (value) { +// if (value?.value == 4) { +// "Status cannot be change to ${value?.name}.".addTranslation.showToast; +// setState(() {}); +// return; +// } +// if (widget.isSender) { +// _formModel.senderMachineStatusName = value?.name; +// _formModel.senderMachineStatusId = value?.id; +// } else { +// _formModel.receiverMachineStatusName = value?.name; +// _formModel.receiverMachineStatusId = value?.id; +// } +// setState(() {}); +// }, +// ); +// }), +// 8.height, +// MultiFilesPicker(label: context.translation.attachImage, files: _files), +// 8.height, +// AppTextFormField( +// initialValue: widget.isSender ? _formModel.senderComment ?? "" : _formModel.receiverComment ?? "", +// labelText: context.translation.comments, +// textInputType: TextInputType.multiline, +// alignLabelWithHint: true, +// onSaved: (value) { +// widget.isSender ? _formModel.senderComment = value : _formModel.receiverComment = value; +// }, +// ), +// 8.height, +// ESignature( +// title: "Signature", +// oldSignature: widget.isSender ? widget.model.senderEngSignature : widget.model.receiverEngSignature, +// newSignature: _signature, +// onSaved: (signature) { +// _signature = signature; +// if (signature == null || signature.isEmpty) return; +// widget.isSender +// ? _formModel.senderEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}" +// : _formModel.receiverEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; +// }, +// ), +// ], +// ), +// ).expanded, +// Padding( +// padding: const EdgeInsets.all(16.0), +// child: AppFilledButton( +// label: context.translation.update, +// onPressed: _update, +// ), +// ), +// ], +// ), +// ), +// ), +// ), +// ); +// } +// +// _buildCard() { +// return Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// context.translation.transferDetails.heading5(context), +// 8.height, +// '${context.translation.assetName}: ${_formModel.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), +// '${context.translation.requesterName}: ${_formModel.receiverEndUserName?.cleanupWhitespace.capitalizeFirstOfEach ?? ""}'.bodyText(context), +// ], +// ).toShadowContainer(context); +// } +// +// String formatDuration(int seconds) { +// int hours = seconds ~/ 3600; +// int minutes = (seconds % 3600) ~/ 60; +// int remainingSeconds = seconds % 60; +// +// String formattedDuration = ''; +// if (hours > 0) { +// formattedDuration += '$hours hour${hours > 1 ? 's' : ''} '; +// } +// if (minutes > 0) { +// formattedDuration += '$minutes minute${minutes > 1 ? 's' : ''} '; +// } +// if (remainingSeconds > 0) { +// formattedDuration += '$remainingSeconds second${remainingSeconds > 1 ? 's' : ''} '; +// } +// if (formattedDuration.isEmpty) { +// formattedDuration = 'Less than a second'; +// } +// +// return formattedDuration.trim(); +// } +// } + +//.....new design.. + import 'dart:convert'; import 'dart:io'; -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/providers/api/asset_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/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/device/asset_transfer.dart'; import 'package:test_sa/models/device/asset_transfer_attachment.dart'; +import 'package:test_sa/models/new_models/assigned_employee.dart'; +import 'package:test_sa/models/new_models/assistant_employee.dart'; +import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; -import 'package:test_sa/providers/asset_transfer/asset_transfer_status_provider.dart'; +import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; +import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/views/app_style/sizing.dart'; +import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/report/service_report_assistant_employee_menu.dart'; import '../../../extensions/text_extensions.dart'; -import '../../../models/lookup.dart'; import '../../../models/ppm/ppm.dart'; import '../../../new_views/app_style/app_color.dart'; import '../../../new_views/common_widgets/app_text_form_field.dart'; import '../../../new_views/common_widgets/default_app_bar.dart'; -import '../../../new_views/common_widgets/single_item_drop_down_menu.dart'; -import '../../widgets/e_signature/e_signature.dart'; import '../../widgets/timer/app_timer.dart'; class UpdateDeviceTransfer extends StatefulWidget { @@ -42,10 +375,7 @@ class UpdateDeviceTransfer extends StatefulWidget { class _UpdateDeviceTransferState extends State { final bool _isLoading = false; - bool _validate = false; - late UserProvider _userProvider; - late SettingProvider _settingProvider; - Uint8List? _signature; + late AssetTransferProvider _deviceTransferProvider; final TextEditingController _requestedQuantityController = TextEditingController(); final AssetTransfer _formModel = AssetTransfer(); @@ -54,27 +384,7 @@ class _UpdateDeviceTransferState extends State { List _files = []; - _update() async { - if (widget.isSender) { - _formModel.senderVisitTimers?.add( - VisitTimers( - id: 0, - startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(), - endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(), - workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60), - ), - ); - } else { - _formModel.receiverVisitTimers?.add( - VisitTimers( - id: 0, - startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(), - endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(), - workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60), - ), - ); - } - + _update({required int status}) async { if (_formModel.tbsTimer?.startAt == null) { await Fluttertoast.showToast(msg: "Working Hours Required"); return false; @@ -83,19 +393,38 @@ class _UpdateDeviceTransferState extends State { await Fluttertoast.showToast(msg: "Please Stop The Timer"); return false; } - _validate = true; if (!(_formKey.currentState!.validate())) { setState(() {}); return false; } _formKey.currentState!.save(); + _formModel.statusValue = status; + _formModel.isSender = widget.isSender; + if (widget.isSender) { _formModel.senderAttachments = []; + _formModel.senderVisitTimers?.add( + VisitTimers( + id: 0, + startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(), + endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(), + workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60), + ), + ); + _formModel.assetTransferEngineerTimers = _formModel.senderVisitTimers; } else { _formModel.receiverAttachments = []; + _formModel.receiverVisitTimers?.add( + VisitTimers( + id: 0, + startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(), + endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(), + workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60), + ), + ); + _formModel.assetTransferEngineerTimers = _formModel.receiverVisitTimers; } - try { for (var file in _files) { String attachmentName = file.path; @@ -103,17 +432,19 @@ class _UpdateDeviceTransferState extends State { attachmentName = file.path.split("/").last; attachmentName = "$attachmentName|${base64Encode(file.readAsBytesSync())}"; } - if (widget.isSender) { _formModel.senderAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName)); + _formModel.attachments = _formModel.senderAttachments; } else { _formModel.receiverAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName)); + _formModel.attachments = _formModel.receiverAttachments; } } } catch (error) { print(error); } - await _deviceTransferProvider.updateRequest(context, assetTransfer: _formModel, isSender: widget.isSender); + + await _deviceTransferProvider.updateRequest(context, model: _formModel); } @override @@ -139,20 +470,16 @@ class _UpdateDeviceTransferState extends State { @override Widget build(BuildContext context) { - _userProvider = Provider.of(context); - _settingProvider = Provider.of(context); _deviceTransferProvider = Provider.of(context, listen: false); - double totalWorkingHours = widget.isSender ? (widget.model.senderVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0) : (widget.model.receiverVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0); - bool isTimerEnable = widget.isSender ? (!(_formModel.senderMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.senderMachineStatusName?.toLowerCase().contains("complete") ?? false)) : (!(_formModel.receiverMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.receiverMachineStatusName?.toLowerCase().contains("complete") ?? false)); return Scaffold( - appBar: DefaultAppBar(title: context.translation.updateRequest), + appBar: DefaultAppBar(title: context.translation.transferAsset), key: _scaffoldKey, body: SafeArea( child: LoadingManager( @@ -167,122 +494,60 @@ class _UpdateDeviceTransferState extends State { SingleChildScrollView( padding: EdgeInsets.all(12 * AppStyle.getScaleFactor(context)), child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - _buildCard(), - 8.height, - AppTextFormField( - initialValue: widget.isSender ? _formModel.senderTravelingHours ?? "" : _formModel.receiverTravelingHours ?? "", - labelText: context.translation.travelingHours, - onChange: (text) { - widget.isSender ? _formModel.senderTravelingHours = text : _formModel.receiverTravelingHours = text; - }, - onSaved: (value) { - widget.isSender ? _formModel.senderTravelingHours = value : _formModel.receiverTravelingHours = value; - //_formModel?.workingHours = double.tryParse(value); - // _formModel.travelingHours = value; - }, - textInputType: TextInputType.number, - //validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only", - ), - 8.height, - if (totalWorkingHours > 0.0) ...[ - Container( - height: 50.toScreenHeight, - padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), - alignment: Alignment.centerLeft, - decoration: BoxDecoration( - color: context.isDark ? AppColor.neutral40 : AppColor.background(context), - borderRadius: BorderRadius.circular(10), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + _timerWidget(context, totalWorkingHours, isTimerEnable), + 8.height, + AppTextFormField( + initialValue: widget.isSender ? _formModel.senderComment ?? "" : _formModel.receiverComment ?? "", + labelText: context.translation.technicalComment, + labelStyle: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral20), + textInputType: TextInputType.multiline, + backgroundColor: AppColor.neutral100, + showShadow: false, + alignLabelWithHint: true, + onSaved: (value) { + widget.isSender ? _formModel.senderComment = value : _formModel.receiverComment = value; + }, ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "Total Working Time", - style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), - ), - Text( - " ${formatDuration(totalWorkingHours.round())}", - style: Theme.of(context).textTheme.bodyLarge, - ), - ], + 8.height, + MultiFilesPicker( + label: context.translation.attachFiles, + files: _files, + buttonColor: AppColor.black10, + onlyImages: false, + buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), ), - ), - 8.height, - ], - AppTimer( - label: context.translation.workingHours, - timer: _formModel.tbsTimer, - enabled: isTimerEnable, - // enabled: widget.isSender ? _formModel.senderEndDate == null : (_formModel?.receiverMachineStatusName?.toLowerCase()?.contains("close") ?? false), - timerProgress: (isRunning) { - isTimerRunning = isRunning; - }, - onChange: (timer) async { - _formModel.tbsTimer = timer; - return true; - }, - ), - 8.height, - Consumer(builder: (context, snapshot, _) { - return SingleItemDropDownMenu( - context: context, - title: widget.isSender ? "Status Sender" : "Status Receiver", //,context.translation.reportStatus, - initialValue: - snapshot.items.firstWhere((element) => element.name == (widget.isSender ? _formModel.senderMachineStatusName : _formModel.receiverMachineStatusName), orElse: null), - onSelect: (value) { - if (value?.value == 4) { - "Status cannot be change to ${value?.name}.".addTranslation.showToast; - setState(() {}); - return; - } - if (widget.isSender) { - _formModel.senderMachineStatusName = value?.name; - _formModel.senderMachineStatusId = value?.id; - } else { - _formModel.receiverMachineStatusName = value?.name; - _formModel.receiverMachineStatusId = value?.id; - } - setState(() {}); - }, - ); - }), - 8.height, - MultiFilesPicker(label: context.translation.attachImage, files: _files), - 8.height, - AppTextFormField( - initialValue: widget.isSender ? _formModel.senderComment ?? "" : _formModel.receiverComment ?? "", - labelText: context.translation.comments, - textInputType: TextInputType.multiline, - alignLabelWithHint: true, - onSaved: (value) { - widget.isSender ? _formModel.senderComment = value : _formModel.receiverComment = value; - }, - ), - 8.height, - ESignature( - title: "Signature", - oldSignature: widget.isSender ? widget.model.senderEngSignature : widget.model.receiverEngSignature, - newSignature: _signature, - onSaved: (signature) { - _signature = signature; - if (signature == null || signature.isEmpty) return; - widget.isSender - ? _formModel.senderEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}" - : _formModel.receiverEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; - }, - ), + 8.height, + ], + ).toShadowContainer(context), + 16.height, + AssistantEmployeeCard( + isSender: widget.isSender, + formModel: _formModel, + ).toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16)), ], ), ).expanded, - Padding( - padding: const EdgeInsets.all(16.0), - child: AppFilledButton( - label: context.translation.update, - onPressed: _update, + FooterActionButton.footerContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + AppFilledButton( + label: context.translation.save, + buttonColor: AppColor.white60, + textColor: AppColor.black10, + onPressed: () => _update(status: 0), + ).expanded, + 12.width, + AppFilledButton( + label: context.translation.complete, + buttonColor: AppColor.primary10, + onPressed: () => _update(status: 1), + ).expanded, + ], ), ), ], @@ -293,37 +558,251 @@ class _UpdateDeviceTransferState extends State { ); } - _buildCard() { + void updateTimer({TimerModel? timer}) { + _formModel.tbsTimer = timer; + if (timer?.startAt != null && timer?.endAt != null) { + _formModel.timerModelList = _formModel.timerModelList ?? []; + _formModel.timerModelList!.add(timer!); + } + // notifyListeners(); + } + + Widget _timerWidget(BuildContext context, double totalWorkingHours, bool isTimerEnable) { return Column( - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, children: [ - context.translation.transferDetails.heading5(context), - 8.height, - '${context.translation.assetName}: ${_formModel.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), - '${context.translation.requesterName}: ${_formModel.receiverEndUserName?.cleanupWhitespace.capitalizeFirstOfEach ?? ""}'.bodyText(context), + AppTimer( + label: context.translation.workingHours, + timer: _formModel.tbsTimer, + width: double.infinity, + enabled: isTimerEnable, + decoration: BoxDecoration( + color: AppColor.neutral100, + borderRadius: BorderRadius.circular(10), + ), + timerProgress: (isRunning) {}, + onChange: (timer) async { + updateTimer(timer: timer); + return true; + }, + ), + if (totalWorkingHours > 0.0) ...[ + 12.height, + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + 'Total Working Time:'.bodyText2(context).custom(color: AppColor.neutral120), + 8.width, + Text( + ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round()), + style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral50, fontWeight: FontWeight.w600), + ), + ], + ), + ], ], - ).toShadowContainer(context); + ); } +} - String formatDuration(int seconds) { - int hours = seconds ~/ 3600; - int minutes = (seconds % 3600) ~/ 60; - int remainingSeconds = seconds % 60; +class AssistantEmployeeCard extends StatefulWidget { + bool? isSender = false; + AssetTransfer? formModel; - String formattedDuration = ''; - if (hours > 0) { - formattedDuration += '$hours hour${hours > 1 ? 's' : ''} '; - } - if (minutes > 0) { - formattedDuration += '$minutes minute${minutes > 1 ? 's' : ''} '; - } - if (remainingSeconds > 0) { - formattedDuration += '$remainingSeconds second${remainingSeconds > 1 ? 's' : ''} '; + AssistantEmployeeCard({super.key, this.isSender, this.formModel}); + + @override + State createState() => _AssistantEmployeeCardState(); +} + +class _AssistantEmployeeCardState extends State { + final TextEditingController _workingHoursController = TextEditingController(text: ''); + bool isCurrentUserIsAssistantEmp = false; + bool isExpanded = false; + List employeeList = []; + AssistantEmployees selectedEmployee = AssistantEmployees(); + + @override + void initState() { + WidgetsBinding.instance.addPostFrameCallback((_) { + getInitialData(); + }); + super.initState(); + } + + Future getInitialData() async { + if (widget.isSender!) { + employeeList = widget.formModel!.assetTransferAssistantEmployeesSender ?? []; + } else { + employeeList = widget.formModel!.assetTransferAssistantEmployeesReceiver ?? []; } - if (formattedDuration.isEmpty) { - formattedDuration = 'Less than a second'; + + widget.formModel?.modelAssistantEmployees = employeeList.isEmpty ? AssetTransferAssistantEmployees() : employeeList[0]; + + AssignedEmployee? assignedUser = AssignedEmployee(); + if (employeeList.isNotEmpty) { + assignedUser = AssignedEmployee( + id: employeeList[0].employeeId, + name: employeeList[0].employeeName, + ); } + selectedEmployee = AssistantEmployees(userId: assignedUser.id, user: assignedUser); + } + + @override + void dispose() { + _workingHoursController.dispose(); + super.dispose(); + } - return formattedDuration.trim(); + @override + Widget build(BuildContext context) { + return Column( + children: [ + SizedBox( + height: 56.toScreenHeight, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + context.translation.assistantEmployee.heading6(context).custom(color: AppColor.black10), + Icon(isExpanded ? Icons.keyboard_arrow_up_rounded : Icons.keyboard_arrow_down_rounded), + ], + ), + ).onPress(() { + setState(() { + isExpanded = !isExpanded; + }); + }), + isExpanded + ? Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ServiceReportAssistantEmployeeMenu( + title: context.translation.select, + backgroundColor: AppColor.neutral100, + assetId: widget.formModel?.assetId ?? 0, + initialValue: selectedEmployee, + onSelect: (employee) { + if (employee == null) { + widget.formModel?.assistantEmployees = []; + } else { + selectedEmployee = employee; + widget.formModel?.assistantEmployees = [employee.copyWith(id: 0)]; + widget.formModel?.modelAssistantEmployees?.employeeId = employee.user?.id; + } + }, + ), + 8.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + ADatePicker( + label: context.translation.startTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: widget.formModel?.modelAssistantEmployees?.startDate, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + // Handle the selected date and time here. + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + widget.formModel?.modelAssistantEmployees?.startDate = selectedDateTime; + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: widget.formModel?.modelAssistantEmployees?.startDate, + endTime: widget.formModel?.modelAssistantEmployees?.endDate, + workingHoursController: _workingHoursController, + updateModel: (hours) { + widget.formModel?.modelAssistantEmployees?.workingHours = hours; + }); + setState(() {}); + } + }); + }, + ).expanded, + 8.width, + ADatePicker( + label: context.translation.endTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: widget.formModel?.modelAssistantEmployees?.endDate, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + if (widget.formModel?.modelAssistantEmployees?.startDate != null && selectedDateTime.isBefore(widget.formModel!.modelAssistantEmployees!.startDate!)) { + "End Date time must be greater then start date".showToast; + return; + } + widget.formModel?.modelAssistantEmployees?.endDate = selectedDateTime; + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: widget.formModel?.modelAssistantEmployees?.startDate, + endTime: widget.formModel?.modelAssistantEmployees?.endDate, + workingHoursController: _workingHoursController, + updateModel: (hours) { + widget.formModel?.modelAssistantEmployees?.workingHours = hours; + }); + setState(() {}); + } + }); + }, + ).expanded, + ], + ), + 8.height, + AppTextFormField( + labelText: context.translation.workingHours, + backgroundColor: AppColor.neutral80, + controller: _workingHoursController, + suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), + initialValue: widget.formModel?.modelAssistantEmployees?.workingHours != null ? widget.formModel?.modelAssistantEmployees?.workingHours.toString() : '', + textAlign: TextAlign.center, + labelStyle: AppTextStyles.textFieldLabelStyle, + enable: false, + showShadow: false, + style: Theme.of(context).textTheme.titleMedium, + ), + 8.height, + AppTextFormField( + initialValue: widget.formModel?.modelAssistantEmployees?.techComment, + labelText: context.translation.technicalComment, + backgroundColor: AppColor.neutral100, + showShadow: false, + labelStyle: AppTextStyles.textFieldLabelStyle, + alignLabelWithHint: true, + textInputType: TextInputType.multiline, + onChange: (value) { + widget.formModel?.modelAssistantEmployees?.techComment = value; + }, + onSaved: (value) { + widget.formModel?.modelAssistantEmployees?.techComment = value; + }, + ), + 16.height, + ], + ) + : const SizedBox(), + ], + ); } } 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 b341c310..908e4da5 100644 --- a/lib/views/pages/user/gas_refill/gas_refill_details.dart +++ b/lib/views/pages/user/gas_refill/gas_refill_details.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/providers/api/gas_refill_comments.dart'; @@ -7,7 +9,10 @@ import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +import 'package:test_sa/views/pages/user/gas_refill/gas_refill_form.dart'; import 'package:test_sa/views/pages/user/gas_refill/request_gas_refill.dart'; +import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/loaders/app_loading.dart'; import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; @@ -30,13 +35,14 @@ class GasRefillDetailsPage extends StatefulWidget { } class _GasRefillDetailsPageState extends State { - GasRefillModel _model = GasRefillModel(gazRefillDetails: []); + GasRefillModel _model = GasRefillModel(gasRefillDetails: []); late UserProvider _userProvider; late GasRefillProvider gasRefillProvider; final bool _isLoading = false; final GlobalKey _formKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); + List _attachments = []; @override void initState() { @@ -61,6 +67,8 @@ class _GasRefillDetailsPageState extends State { return const ALoading(); } else if (snap.hasData) { _model = snap.data as GasRefillModel; + _attachments = _model.gasRefillAttachments?.map((e) => File(e.attachmentName ?? '')).toList() ?? []; + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -68,6 +76,14 @@ class _GasRefillDetailsPageState extends State { padding: const EdgeInsets.all(16), child: informationCard(_model), ).expanded, + if (_userProvider.user!.type == UsersTypes.engineer && (_model.status!.id! != 5833))//TODO need to check this value for complete status. + AppFilledButton( + onPressed: () async { + await Navigator.of(context).push(MaterialPageRoute(builder: (_) => GasRefillForm(gasRefillModel: _model))); + // getVisitData(); + }, + label: context.translation.updateRequest, + ).paddingAll(16) ], ); } @@ -109,133 +125,124 @@ class _GasRefillDetailsPageState extends State { context.translation.gasRefillRequest.heading5(context), 8.height, - '${context.translation.gasRequest}: ${gasRefillModel.gazRefillDetails![0].gasType?.name}'.bodyText(context), - '${context.translation.cylinderType}: ${gasRefillModel.gazRefillDetails![0].cylinderType?.name}'.bodyText(context), - '${context.translation.cylinderSize}: ${gasRefillModel.gazRefillDetails![0].cylinderSize?.name}'.bodyText(context), + '${context.translation.gasRequest}: ${gasRefillModel.gasRefillDetails![0].gasType?.name}'.bodyText(context), + '${context.translation.cylinderType}: ${gasRefillModel.gasRefillDetails![0].cylinderType?.name}'.bodyText(context), + '${context.translation.cylinderSize}: ${gasRefillModel.gasRefillDetails![0].cylinderSize?.name}'.bodyText(context), '${context.translation.site}: ${gasRefillModel.site?.name?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), '${context.translation.department}: ${gasRefillModel.department?.name?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), - '${context.translation.requestNo}: ${gasRefillModel.gazRefillNo}'.bodyText(context), + '${context.translation.requestNo}: ${gasRefillModel.gasRefillNo}'.bodyText(context), //TODO need to confirm where to display this new data... - infoText(label:context.translation.gasRequest ,value:gasRefillModel.extensionNo ), - infoText(label:context.translation.employeeId ,value:gasRefillModel.employeeId ), - infoText(label:context.translation.name ,value:gasRefillModel.name ), - infoText(label:context.translation.createdDate ,value:gasRefillModel.createdDate?.toInitialVisitCardFormat), + infoText(label: context.translation.gasRequest, value: gasRefillModel.extensionNo), + infoText(label: context.translation.employeeId, value: gasRefillModel.employeeId), + infoText(label: context.translation.name, value: gasRefillModel.name), + infoText(label: context.translation.createdDate, value: gasRefillModel.createdDate?.toInitialVisitCardFormat), const Divider().defaultStyle(context), - '${context.translation.requestedQuantity}: ${gasRefillModel.gazRefillDetails![0].requestedQty ?? 0}'.bodyText(context), - '${context.translation.deliveredQuantity}: ${gasRefillModel.gazRefillDetails![0].deliverdQty ?? 0}'.bodyText(context), + '${context.translation.requestedQuantity}: ${gasRefillModel.gasRefillDetails![0].requestedQty ?? 0}'.bodyText(context), + '${context.translation.deliveredQuantity}: ${gasRefillModel.gasRefillDetails![0].deliverdQty ?? 0}'.bodyText(context), 8.height, if (gasRefillModel.comment?.isNotEmpty ?? false) ...[ const Divider().defaultStyle(context), gasRefillModel.comment!.bodyText(context), 8.height, - ] - ], - ).expanded, - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - if (_userProvider.user!.type == UsersTypes.engineer && (gasRefillModel.status?.value ?? 0) != 2) - "edit".toSvgAsset(height: 48, width: 48).onPress( - () async { - _model.fromGasRefillModel(gasRefillModel); - // setState(() {}); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => RequestGasRefill(gasRefillModel: gasRefillModel), - ), - ).then((value) { - if (value != null) { - _model = value; - setState(() {}); - } - }); - }, + ], + if (_attachments.isNotEmpty) ...[ + const Divider().defaultStyle(context), + context.translation.attachments.bodyText(context), + 8.height, + MultiFilesPicker( + label: context.translation.attachments, + files: _attachments, + enabled: false, + onlyImages: false, ), - if (_userProvider.user!.type == UsersTypes.engineer && (gasRefillModel.status?.value ?? 0) != 2) 8.height, - Text( - (widget.date ?? gasRefillModel.expectedDate)?.toServiceRequestCardFormat ?? "", - textAlign: TextAlign.end, - style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50), - ), + 12.height, + ], ], + ).expanded, + if (_userProvider.user!.type == UsersTypes.engineer && (gasRefillModel.status?.value ?? 0) != 2) 8.height, + Text( + (widget.date ?? gasRefillModel.expectedDate)?.toServiceRequestCardFormat ?? "", + textAlign: TextAlign.end, + style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50), ), ], + ).paddingOnly(top: 16, start: 16, end: 16), /// TBD - (_userProvider.user!.type == UsersTypes.normal_user - ? Container( - height: 50, - padding: const EdgeInsets.only(left: 16, right: 16), - alignment: Alignment.center, - width: double.infinity, - decoration: ShapeDecoration( - color: context.isDark ? AppColor.neutral50 : AppColor.neutral30, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(14), - bottomRight: Radius.circular(14), - ), - ), - ), - child: Row( - children: [ - Text( - '${context.translation.commentHere}...', - style: AppTextStyles.heading6.copyWith( - color: (context.isDark ? AppColor.neutral30 : AppColor.neutral50).withOpacity(.6), - ), - ).expanded, - "comment_send".toSvgAsset(width: 24, color: context.isDark ? AppColor.primary50 : AppColor.primary70), - ], - ), - ) - : Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Divider().defaultStyle(context), - 8.height, - Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - context.translation.viewComments, - style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)), - ), - 4.width, - Icon( - Icons.arrow_forward, - color: AppColor.blueStatus(context), - size: 14, - ) - ], - ), - ], - ).paddingOnly(bottom: 16, start: 16, end: 16)) - .onPress(() { - showModalBottomSheet( - context: context, - useSafeArea: true, - isScrollControlled: true, - useRootNavigator: true, - backgroundColor: Colors.transparent, - builder: (context) => GasRefillCommentsBottomSheet(requestId: gasRefillModel.id.toString()), - ); - }), + // (_userProvider.user!.type == UsersTypes.normal_user + // ? Container( + // height: 50, + // padding: const EdgeInsets.only(left: 16, right: 16), + // alignment: Alignment.center, + // width: double.infinity, + // decoration: ShapeDecoration( + // color: context.isDark ? AppColor.neutral50 : AppColor.neutral30, + // shape: const RoundedRectangleBorder( + // borderRadius: BorderRadius.only( + // bottomLeft: Radius.circular(14), + // bottomRight: Radius.circular(14), + // ), + // ), + // ), + // child: Row( + // children: [ + // Text( + // '${context.translation.commentHere}...', + // style: AppTextStyles.heading6.copyWith( + // color: (context.isDark ? AppColor.neutral30 : AppColor.neutral50).withOpacity(.6), + // ), + // ).expanded, + // "comment_send".toSvgAsset(width: 24, color: context.isDark ? AppColor.primary50 : AppColor.primary70), + // ], + // ), + // ) + // : Column( + // mainAxisSize: MainAxisSize.min, + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // const Divider().defaultStyle(context), + // 8.height, + // Row( + // mainAxisSize: MainAxisSize.min, + // children: [ + // Text( + // context.translation.viewComments, + // style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)), + // ), + // 4.width, + // Icon( + // Icons.arrow_forward, + // color: AppColor.blueStatus(context), + // size: 14, + // ) + // ], + // ), + // ], + // ).paddingOnly(bottom: 16, start: 16, end: 16)) + // .onPress(() { + // showModalBottomSheet( + // context: context, + // useSafeArea: true, + // isScrollControlled: true, + // useRootNavigator: true, + // backgroundColor: Colors.transparent, + // builder: (context) => GasRefillCommentsBottomSheet(requestId: gasRefillModel.id.toString()), + // ); + // }), ], ).toShadowContainer(context, padding: 0); } - Widget infoText({String ?label,String ?value,}){ - if(value==null||value.isEmpty){ - return const SizedBox(); - } - else { + Widget infoText({ + String? label, + String? value, + }) { + if (value == null || value.isEmpty) { + return const SizedBox(); + } else { return '$label: $value'.bodyText(context); } - } } diff --git a/lib/views/pages/user/gas_refill/gas_refill_form.dart b/lib/views/pages/user/gas_refill/gas_refill_form.dart new file mode 100644 index 00000000..f08f7ae3 --- /dev/null +++ b/lib/views/pages/user/gas_refill/gas_refill_form.dart @@ -0,0 +1,385 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/all_requests_provider.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/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/timer_model.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; +import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart'; +import 'package:test_sa/providers/loading_list_notifier.dart'; +import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; +import 'package:test_sa/service_request_latest/views/components/action_button/footer_action_button.dart'; +import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; + +import '../../../../extensions/text_extensions.dart'; +import '../../../../models/new_models/gas_refill_model.dart'; +import '../../../../new_views/common_widgets/app_text_form_field.dart'; +import '../../../../new_views/common_widgets/default_app_bar.dart'; +import '../../../../new_views/common_widgets/single_item_drop_down_menu.dart'; +import '../../../widgets/timer/app_timer.dart'; + +class GasRefillForm extends StatefulWidget { + static const String id = "/gas-refill-form"; + final GasRefillModel? gasRefillModel; + + const GasRefillForm({this.gasRefillModel, Key? key}) : super(key: key); + + @override + State createState() => _GasRefillFormState(); +} + +class _GasRefillFormState extends State { + final bool _isLoading = false; + bool _validate = false; + Uint8List? _engineerSignature; + Uint8List? _nurseSignature; + double totalWorkingHours = 0.0; + + late UserProvider _userProvider; + late SettingProvider _settingProvider; + GasRefillProvider? _gasRefillProvider; + GasRefillDetails _currentDetails = GasRefillDetails(); + final TextEditingController _deliveredQuantityController = TextEditingController(); + final TextEditingController _commentController = TextEditingController(); + final TextEditingController _workingHoursController = TextEditingController(); + + final GasRefillModel _formModel = GasRefillModel(gasRefillDetails: []); + final GlobalKey _formKey = GlobalKey(); + final GlobalKey _DetailsKey = GlobalKey(); + final GlobalKey _scaffoldKey = GlobalKey(); + bool _firstTime = true; + + Lookup? _deliveredQuantity; + List _attachments = []; + + static List deliveredQuantity = [ + Lookup(name: "1", id: 1, value: 1), + Lookup(name: "2", id: 2, value: 2), + Lookup(name: "3", id: 3, value: 3), + Lookup(name: "4", id: 4, value: 4), + Lookup(name: "5", id: 5, value: 5) + ]; + + @override + void initState() { + super.initState(); + _gasRefillProvider ??= Provider.of(context, listen: false); + + if (widget.gasRefillModel != null) { + _formModel.fromGasRefillModel(widget.gasRefillModel!); + + totalWorkingHours = + _formModel.gasRefillTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDate!).difference(DateTime.parse(item.startDate!)).inSeconds) ?? 0; + _commentController.text = _formModel.techComment ?? ""; + try { + _deliveredQuantity = deliveredQuantity.singleWhere((element) => element.value == _formModel.gasRefillDetails![0].deliverdQty); + _currentDetails.deliverdQty = _deliveredQuantity!.value; + } catch (ex) {} + } + if (_formModel.gasRefillAttachments != null && _formModel.gasRefillAttachments!.isNotEmpty) { + _attachments.addAll(_formModel.gasRefillAttachments!.map((e) => File(e.attachmentName!)).toList()); + } + } + + @override + void setState(VoidCallback fn) { + if (mounted) super.setState(() {}); + } + + _onSubmit(BuildContext context, int status) 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; + } + if (_currentDetails.deliverdQty == null) { + await Fluttertoast.showToast(msg: "Delivered Quantity is Required"); + return false; + } + _formModel.gasRefillDetails = []; + _formModel.gasRefillDetails?.add(_currentDetails); + + showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); + _formModel.gasRefillTimers = _formModel.gasRefillTimers ?? []; + + _formModel.timerModelList?.forEach((timer) { + int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds; + _formModel.gasRefillTimers?.add( + GasRefillTimer( + id: 0, + startDate: timer.startAt!.toIso8601String(), // Handle potential null + endDate: timer.endAt?.toIso8601String(), // Handle potential null + workingHours: ((durationInSecond) / 60 / 60), + ), + ); + }); + _formModel.gasRefillAttachments = []; + for (var item in _attachments) { + _formModel.gasRefillAttachments + ?.add(GasRefillAttachments(id: 0,gasRefillId: _formModel.id??0, attachmentName: ServiceRequestUtils.isLocalUrl(item.path) ? "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}" : item.path)); + } + await _gasRefillProvider?.updateGasRefill(status: status, model: _formModel).whenComplete(() { + if (status == 1) { + AllRequestsProvider allRequestsProvider = Provider.of(context, listen: false); + // when click complete then this request remove from the list and status changes to closed.. + _gasRefillProvider?.reset(); + allRequestsProvider.getAllRequests(context, typeTransaction: 2); + } + Navigator.pop(context); + Navigator.pop(context); + }); + } + + @override + void dispose() { + _deliveredQuantityController.dispose(); + _commentController.dispose(); + _workingHoursController.dispose(); + super.dispose(); + } + + void updateTimer({TimerModel? timer}) { + _formModel.timer = timer; + if (timer?.startAt != null && timer?.endAt != null) { + _formModel.timerModelList = _formModel.timerModelList ?? []; + _formModel.timerModelList!.add(timer!); + } + // notifyListeners(); + } + + @override + Widget build(BuildContext context) { + _userProvider = Provider.of(context); + _settingProvider = Provider.of(context); + if (_firstTime) { + String? clientName; + if (widget.gasRefillModel != null) { + //_formModel.status = widget.gasRefillModel?.status ?? Lookup(value: 0); + _gasRefillProvider!.expectedDateTime = DateTime.tryParse(_formModel.expectedDate ?? ""); + _formModel.timer = TimerModel(startAt: DateTime.tryParse(widget.gasRefillModel?.startDate ?? ""), endAt: DateTime.tryParse(widget.gasRefillModel?.endDate ?? "")); + clientName = _formModel.site?.custName; + } else { + _formModel.timer = null; + clientName = _userProvider.user?.clientName; + } + + // HospitalsProvider().getHospitalsListByVal(searchVal: clientName ?? '').then((value) { + // _gasRefillProvider!.hospital = value.firstWhere((element) => element.name == 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(() {}); + // }); + } + double totalWorkingHours = _formModel.gasRefillTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDate!).difference(DateTime.parse(item.startDate!)).inSeconds) ?? 0; + + return Scaffold( + appBar: DefaultAppBar(title: context.translation.gasRefill), + key: _scaffoldKey, + body: Form( + key: _formKey, + child: SafeArea( + child: LoadingManager( + isLoading: _isLoading, + isFailedLoading: false, + stateCode: 200, + onRefresh: () async {}, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // context.translation.gasRefill.heading5(context), + // 8.height, + // '${context.translation.gasRequest}: ${widget.gasRefillModel!.gasRefillDetails![0].gasType!.name}'.bodyText(context), + // '${context.translation.cylinderType}: ${widget.gasRefillModel!.gasRefillDetails![0].cylinderType!.name}'.bodyText(context), + // '${context.translation.cylinderSize}: ${widget.gasRefillModel!.gasRefillDetails![0].cylinderSize!.name}'.bodyText(context), + // '${context.translation.quantity}: ${widget.gasRefillModel!.gasRefillDetails![0].requestedQty ?? 0}'.bodyText(context), + // '${context.translation.site}: ${widget.gasRefillModel!.site?.name}'.bodyText(context), + // ], + // ).toShadowContainer(context), + 8.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.quantity, + backgroundColor: AppColor.neutral100, + showShadow: false, + initialValue: _deliveredQuantity, + staticData: deliveredQuantity, + onSelect: (value) { + _deliveredQuantity = value; + _currentDetails.deliverdQty = value!.value; + }, + ), + 8.height, + // AppTextFormField( + // initialValue: _formModel.gasRefillDetails?[0].deliverdQty?.toString() ?? "", + // labelText: context.translation.deliveredQuantity, + // onSaved: (value) { + // _currentDetails.deliverdQty = double.tryParse(value); + // }, + // textInputType: TextInputType.number, + // controller: _deliveredQuantityController, + // validator: (value) => value == null || value.isEmpty + // ? context.translation.requiredField + // : Validator.isNumeric(value) + // ? null + // : context.translation.onlyNumbers, + // ), + // 8.height, + _timerWidget(context, totalWorkingHours), + 8.height, + // SingleItemDropDownMenu( + // context: context, + // title: context.translation.requestStatus, + // initialValue: _formModel.status, + // onSelect: (value) { + // if (value?.value == 0) { + // "Status cannot be change to ${value?.name}.".addTranslation.showToast; + // setState(() {}); + // return; + // } + // if (value != null) { + // _formModel.status = value; + // } + // }, + // ), + // 8.height, + + // 8.height, + + /// TBD + AppTextFormField( + labelText: context.translation.technicalComment, + textInputType: TextInputType.multiline, + alignLabelWithHint: true, + backgroundColor: AppColor.neutral100, + showShadow: false, + controller: _commentController, + onChange: (value) { + _formModel.techComment = value; + }, + onSaved: (value) {}, + ), + 16.height, + MultiFilesPicker( + label: context.translation.attachFiles, + files: _attachments, + buttonColor: AppColor.black10, + onlyImages: false, + buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), + ), + 8.height, + // ESignature( + // title: "Engineer Signature", + // oldSignature: widget.gasRefillModel?.engSignature, + // newSignature: _engineerSignature, + // onSaved: (signature) { + // _engineerSignature = signature; + // if (signature == null || signature.isEmpty) return; + // _formModel.engSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + // //base64Encode(signature); + // }, + // ), + // 8.height, + // ESignature( + // title: "Nurse Signature", + // oldSignature: widget.gasRefillModel?.nurseSignature, + // newSignature: _nurseSignature, + // onSaved: (signature) { + // _nurseSignature = signature; + // if (signature == null || signature.isEmpty) return; + // _formModel.nurseSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; + // //base64Encode(signature); + // }, + // ), + ], + ).toShadowContainer(context), + ).expanded, + FooterActionButton.footerContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + AppFilledButton( + label: context.translation.save, + buttonColor: AppColor.white60, + textColor: AppColor.black10, + onPressed: () => _onSubmit(context, 0), + ).expanded, + 12.width, + AppFilledButton( + label: context.translation.complete, + buttonColor: AppColor.primary10, + onPressed: () => _onSubmit(context, 1), + ).expanded, + ], + ), + ), + ], + )), + ), + ), + ); + } + + Widget _timerWidget(BuildContext context, double totalWorkingHours) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + AppTimer( + label: context.translation.workingHours, + timer: _formModel.timer, + //TODO need to fix this.. + // enabled: _formModel.endDate == null, + width: double.infinity, + decoration: BoxDecoration( + color: AppColor.neutral100, + borderRadius: BorderRadius.circular(10), + ), + timerProgress: (isRunning) {}, + onChange: (timer) async { + updateTimer(timer: timer); + return true; + }, + ), + if (totalWorkingHours > 0.0) ...[ + 12.height, + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + 'Total Working Time:'.bodyText2(context).custom(color: AppColor.neutral120), + 8.width, + Text( + ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round()), + style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral50, fontWeight: FontWeight.w600), + ), + ], + ), + ], + ], + ); + } +} 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 8ea8b9d7..d05ea482 100644 --- a/lib/views/pages/user/gas_refill/request_gas_refill.dart +++ b/lib/views/pages/user/gas_refill/request_gas_refill.dart @@ -8,7 +8,6 @@ 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/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart'; @@ -53,13 +52,12 @@ class _RequestGasRefillState extends State { final TextEditingController _commentController = TextEditingController(); final TextEditingController _workingHoursController = TextEditingController(); - final GasRefillModel _formModel = GasRefillModel(gazRefillDetails: []); + final GasRefillModel _formModel = GasRefillModel(gasRefillDetails: []); final GlobalKey _formKey = GlobalKey(); final GlobalKey _DetailsKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); bool _firstTime = true; - Lookup? _deliveredQuantity; static List deliveredQuantity = [ @@ -77,7 +75,7 @@ class _RequestGasRefillState extends State { _formModel.fromGasRefillModel(widget.gasRefillModel!); _commentController.text = _formModel.comment ?? ""; try { - _deliveredQuantity = deliveredQuantity.singleWhere((element) => element.value == _formModel.gazRefillDetails![0].deliverdQty); + _deliveredQuantity = deliveredQuantity.singleWhere((element) => element.value == _formModel.gasRefillDetails![0].deliverdQty); _currentDetails.deliverdQty = _deliveredQuantity!.value; } catch (ex) {} } @@ -101,7 +99,7 @@ class _RequestGasRefillState extends State { await Fluttertoast.showToast(msg: "Please Stop The Timer"); return false; } - if (_formModel.gazRefillDetails?.isNotEmpty ?? false) { + if (_formModel.gasRefillDetails?.isNotEmpty ?? false) { if (!(await _addNewModel(context))) return; } @@ -135,7 +133,7 @@ class _RequestGasRefillState extends State { } } - bool _addNewModel(BuildContext context) { + bool _addNewModel(BuildContext context) { _validate = true; if (_currentDetails.deliverdQty == null) { Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.quantity}"); @@ -147,15 +145,15 @@ class _RequestGasRefillState extends State { // return false; // } _formKey.currentState!.save(); - _currentDetails.gasType = _formModel.gazRefillDetails![0].gasType; - _currentDetails.cylinderSize = _formModel.gazRefillDetails![0].cylinderSize; - _currentDetails.cylinderType = _formModel.gazRefillDetails![0].cylinderType; - _currentDetails.requestedQty = _formModel.gazRefillDetails![0].requestedQty; - if (!( _currentDetails.validate(context))) { + _currentDetails.gasType = _formModel.gasRefillDetails![0].gasType; + _currentDetails.cylinderSize = _formModel.gasRefillDetails![0].cylinderSize; + _currentDetails.cylinderType = _formModel.gasRefillDetails![0].cylinderType; + _currentDetails.requestedQty = _formModel.gasRefillDetails![0].requestedQty; + if (!(_currentDetails.validate(context))) { setState(() {}); return false; } - _formModel.gazRefillDetails![0].deliverdQty = _currentDetails.deliverdQty; + _formModel.gasRefillDetails![0].deliverdQty = _currentDetails.deliverdQty; _validate = false; // Scrollable.ensureVisible(_DetailsKey.currentContext); _deliveredQuantityController.clear(); @@ -176,7 +174,6 @@ class _RequestGasRefillState extends State { @override Widget build(BuildContext context) { - _userProvider = Provider.of(context); _settingProvider = Provider.of(context); _gasRefillProvider ??= Provider.of(context, listen: false); @@ -192,12 +189,11 @@ class _RequestGasRefillState extends State { clientName = _userProvider.user?.clientName; } - - HospitalsProvider().getHospitalsListByVal(searchVal: clientName??'').then((value) { - _gasRefillProvider!.hospital = value.firstWhere((element) => element.name == 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); + HospitalsProvider().getHospitalsListByVal(searchVal: clientName ?? '').then((value) { + _gasRefillProvider!.hospital = value.firstWhere((element) => element.name == 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(() {}); }); @@ -226,10 +222,10 @@ class _RequestGasRefillState extends State { children: [ context.translation.gasRefill.heading5(context), 8.height, - '${context.translation.gasRequest}: ${widget.gasRefillModel!.gazRefillDetails![0].gasType!.name}'.bodyText(context), - '${context.translation.cylinderType}: ${widget.gasRefillModel!.gazRefillDetails![0].cylinderType!.name}'.bodyText(context), - '${context.translation.cylinderSize}: ${widget.gasRefillModel!.gazRefillDetails![0].cylinderSize!.name}'.bodyText(context), - '${context.translation.quantity}: ${widget.gasRefillModel!.gazRefillDetails![0].requestedQty ?? 0}'.bodyText(context), + '${context.translation.gasRequest}: ${widget.gasRefillModel!.gasRefillDetails![0].gasType!.name}'.bodyText(context), + '${context.translation.cylinderType}: ${widget.gasRefillModel!.gasRefillDetails![0].cylinderType!.name}'.bodyText(context), + '${context.translation.cylinderSize}: ${widget.gasRefillModel!.gasRefillDetails![0].cylinderSize!.name}'.bodyText(context), + '${context.translation.quantity}: ${widget.gasRefillModel!.gasRefillDetails![0].requestedQty ?? 0}'.bodyText(context), '${context.translation.site}: ${widget.gasRefillModel!.site?.name}'.bodyText(context), ], ).toShadowContainer(context), diff --git a/lib/views/pages/user/land_page.dart b/lib/views/pages/user/land_page.dart index 198ba167..da3c34ce 100644 --- a/lib/views/pages/user/land_page.dart +++ b/lib/views/pages/user/land_page.dart @@ -19,7 +19,7 @@ // // import '../../../models/enums/user_types.dart'; // import '../../widgets/land_page/land_page_item.dart'; -// import '../device_transfer/request_device_transfer.dart'; +// import '../device_transfer/create__asset_transfer_request.dart'; // import 'requests/requests_page.dart'; // // @Deprecated("Use the page which is inside the [new_views/pages/land_page] folder") diff --git a/lib/views/pages/user/ppm/ppm_details_page.dart b/lib/views/pages/user/ppm/ppm_details_page.dart index 107cc4d7..0ad5d7a0 100644 --- a/lib/views/pages/user/ppm/ppm_details_page.dart +++ b/lib/views/pages/user/ppm/ppm_details_page.dart @@ -97,7 +97,7 @@ class _PpmDetailsPageState extends State { // '${context.translation.expectDate}: ${planPreventiveVisit.expectedDate?.toAssetDetailsFormat ?? ""}'.bodyText(context), //todo @baha, '${context.translation.actualDate}: ${planPreventiveVisit.acutalDateOfVisit?.toIso8601String().toAssetDetailsFormat ?? ""}'.bodyText(context), //todo @baha, const Divider().defaultStyle(context), - '${context.translation.engineerName}: ${planPreventiveVisit.assignedEmployee?.userName ?? ""}'.bodyText(context), //todo @baha, + '${context.translation.assignedEmployee}: ${planPreventiveVisit.assignedEmployee?.userName ?? ""}'.bodyText(context), //todo @baha, '${context.translation.site}: ${planPreventiveVisit.siteName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), //todo @baha, '${context.translation.building}: ${planPreventiveVisit.buildingName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), //todo @baha, '${context.translation.floor}: ${planPreventiveVisit.floorName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), //todo @baha, @@ -106,14 +106,24 @@ class _PpmDetailsPageState extends State { ], ).toShadowContainer(context).paddingAll(16), ).expanded, - if (userProvider!.user!.type == UsersTypes.engineer && (planPreventiveVisit.visitStatus!.id! != 270 && planPreventiveVisit.visitStatus!.id! != 269)) + if (userProvider!.user!.type == UsersTypes.engineer && (!ppmProvider.isReadOnly))...[ AppFilledButton( onPressed: () async { await Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdatePpm(ppm: null, planPreventiveVisit: planPreventiveVisit))); getVisitData(); }, - label: context.translation.updateRequest, + label: context.translation.updateWorkOrder, ).paddingAll(16) + ] + else ...[ + AppFilledButton( + onPressed: () async { + await Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdatePpm(ppm: null, planPreventiveVisit: planPreventiveVisit))); + getVisitData(); + }, + label: context.translation.viewDetails, + ).paddingAll(16) + ] ]); }), ), diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart index 16cb8850..295eff91 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_inspection_card.dart @@ -52,16 +52,8 @@ class _RoomInspectionCardState extends State { ).toShadowContainer(context).paddingOnly(top: 12); } - Widget inspectionStatusRadioWidget({ - required int index, - required PlanRecurrentMedicalTaskRoomTabAttributes model, - required BuildContext context, - }) { - bool status = model.attribute != null - ? model.attributeValue == 'true' - ? true - : false - : false; + Widget inspectionStatusRadioWidget({required int index, required PlanRecurrentMedicalTaskRoomTabAttributes model, required BuildContext context}) { + bool status = (model.attribute == null || model.attributeValue == null) ? true : (model.attribute != null ? (model.attributeValue == 'true' ? true : false) : false); return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -71,7 +63,7 @@ class _RoomInspectionCardState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - model.attribute!.name!, + model.attribute?.name ?? '', overflow: TextOverflow.ellipsis, maxLines: 1, style: AppTextStyles.bodyText2.copyWith(color: AppColor.white936), diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart index 9d7f01b0..cbf5c9c7 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/room_tabs_widget.dart @@ -76,7 +76,8 @@ class _RoomTabsWidgetState extends State { ? const ALoading().paddingOnly(top: 150) : ListView( shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, + physics: const NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, children: widget.model!.planRecurrentMedicalTaskRooms![selectedIndex].planRecurrentMedicalTaskRoomTabs!.map((card) { return RoomInspectionCard(inspectionModel: card); }).toList(), diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart index 407449bc..7034f7ca 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/components/task_info_widget.dart @@ -6,11 +6,9 @@ import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; -import 'package:test_sa/models/all_requests_and_count_model.dart'; -import 'package:test_sa/models/ppm/ppm.dart'; import 'package:test_sa/models/ppm/recurrent_wo.dart'; -import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; +import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart'; import 'package:test_sa/views/widgets/timer/app_timer.dart'; @@ -40,7 +38,7 @@ class RecurrentTaskInfoWidget extends StatelessWidget { 2.height, '${context.translation.taskNo}: ${model!.taskNo!}'.bodyText2(context).custom(color: AppColor.neutral120), '${context.translation.site}: ${model!.site!.siteName!}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.assignEngineer}: ${model!.engineer!.userName ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.assignedEmployee}: ${model!.engineer!.userName ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), '${context.translation.scheduledDate}: ${model!.scheduleDate!.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120), ], ).toShadowContainer(context), @@ -50,17 +48,21 @@ class RecurrentTaskInfoWidget extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - buildingInfoWidget(label: context.translation.department, value: model?.department?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), + buildingInfoWidget(label: context.translation.department, value: model!.department?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), 8.height, - buildingInfoWidget(label: context.translation.floor, value: model?.floor?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), + buildingInfoWidget(label: context.translation.floor, value: model!.floor?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), 8.height, - buildingInfoWidget(label: context.translation.room, value: model?.room?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), + buildingInfoWidget(label: context.translation.room, value: model!.room?.name?.cleanupWhitespace.capitalizeFirstOfEach, context: context), 8.height, - _timerWidget(context, model!.totalWorkingHours!) + _timerWidget(context, model!.totalWorkingHours!), + 8.height, + _commentWidget(context: context, model: model) ], // ], ).toShadowContainer(context, padding: 12) - : _timerWidget(context, model!.totalWorkingHours!).toShadowContainer(context, padding: 12), + : Column( + children: [_timerWidget(context, model!.totalWorkingHours!), 8.height, _commentWidget(context: context, model: model)], + ).toShadowContainer(context, padding: 12), ], ); } @@ -74,7 +76,7 @@ class RecurrentTaskInfoWidget extends StatelessWidget { label: context.translation.timer, timer: snapshot.recurrentWoData?.recurrentWoTimerModel, width: double.infinity, - // enabled: snapshot.recurrentWoData?.recurrentWoTimerModel?.endAt == null, + enabled: snapshot.recurrentWoData?.status?.value != 1, decoration: BoxDecoration( color: AppColor.neutral100, borderRadius: BorderRadius.circular(10), @@ -104,6 +106,24 @@ class RecurrentTaskInfoWidget extends StatelessWidget { ); }); } + + Widget _commentWidget({RecurrentWoData? model, required BuildContext context}) { + return AppTextFormField( + initialValue: model?.comment, + labelText: context.translation.comment, + backgroundColor: AppColor.neutral100, + showShadow: false, + labelStyle: AppTextStyles.textFieldLabelStyle, + alignLabelWithHint: true, + textInputType: TextInputType.multiline, + onChange: (value) { + model?.comment = value; + }, + onSaved: (value) { + model?.comment = value; + }, + ); + } } Widget buildingInfoWidget({required String label, required String? value, required BuildContext context}) { @@ -118,10 +138,9 @@ Widget buildingInfoWidget({required String label, required String? value, requir ), 3.height, Text( - value??'', + value ?? '', style: AppTextStyles.bodyText2.copyWith(color: AppColor.black10), ) ], ).toShadowContainer(context, backgroundColor: AppColor.neutral100, borderRadius: 10, paddingObject: EdgeInsets.all(12.toScreenHeight), showShadow: false); } - diff --git a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart index 8b3eb979..c7ca4c5a 100644 --- a/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart +++ b/lib/views/pages/user/ppm/ppm_work_order/recurrent_wo/recurrent_work_order_view.dart @@ -48,7 +48,12 @@ class _RecurrentWorkOrderViewState extends State { Widget build(BuildContext context) { return Consumer(builder: (context, requestProvider, child) { return Scaffold( - appBar: DefaultAppBar(title: context.translation.recurrentWo), + appBar: DefaultAppBar( + title: context.translation.recurrentWo, + onWillPopScope: () { + _updateTask(context: context, status: 0); + }, + ), body: allRequestsProvider!.isLoading ? const ALoading() : requestProvider.recurrentWoData != null @@ -60,7 +65,6 @@ class _RecurrentWorkOrderViewState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ RecurrentTaskInfoWidget(model: requestProvider.recurrentWoData), - // 8.height, requestProvider.recurrentWoData!.planRecurrentMedicalTaskRooms!.isNotEmpty ? Column( children: [ @@ -72,29 +76,35 @@ class _RecurrentWorkOrderViewState extends State { ], ).paddingAll(12), ).paddingOnly(bottom: 85), - FooterActionButton.footerContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - AppFilledButton( - label: context.translation.save, - buttonColor: AppColor.white60, - textColor: AppColor.black10, - onPressed: () => _updateTask(context: context, status: 0), - ).expanded, - 12.width, - AppFilledButton( - label: context.translation.complete, - buttonColor: AppColor.primary10, - onPressed: () => _updateTask(context: context, status: 1), - ).expanded, - ], + if (requestProvider.recurrentWoData?.status?.value != 1) ...[ + FooterActionButton.footerContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + AppFilledButton( + label: context.translation.save, + buttonColor: AppColor.white60, + textColor: AppColor.black10, + onPressed: () => _updateTask(context: context, status: 0), + ).expanded, + 12.width, + AppFilledButton( + label: context.translation.complete, + buttonColor: AppColor.primary10, + onPressed: () => _updateTask(context: context, status: 1), + ).expanded, + ], + ), ), - ), + ] ], ) : NoDataFound(message: context.translation.noDataFound).center, - ); + ).handlePopScope( + cxt: context, + onSave: () { + _updateTask(context: context, status: 0); + }); }); } } @@ -104,11 +114,7 @@ void _updateTask({required BuildContext context, required int status}) async { if (validate(model: allRequestsProvider.recurrentWoData!)) { allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers = allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers ?? []; - DateTime? startTime = allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.startAt; - DateTime? endTime = allRequestsProvider.recurrentWoData?.recurrentWoTimerModel?.endAt; - // final duration = (endTime?.difference(startTime!)); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); - allRequestsProvider.recurrentWoData?.timerModelList?.forEach((timer) { int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds; allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers?.add( diff --git a/lib/views/pages/user/ppm/update_ppm/ppm_calibration_tools_form.dart b/lib/views/pages/user/ppm/update_ppm/ppm_calibration_tools_form.dart index f6484ace..9684d49a 100644 --- a/lib/views/pages/user/ppm/update_ppm/ppm_calibration_tools_form.dart +++ b/lib/views/pages/user/ppm/update_ppm/ppm_calibration_tools_form.dart @@ -8,6 +8,7 @@ import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/device/asset.dart'; import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/plan_preventive_visit/plan_preventive_visit_model.dart'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart'; @@ -29,7 +30,8 @@ class _PpmCalibrationToolsFormState extends State { @override Widget build(BuildContext context) { final userProvider = Provider.of(context); - int totalTabs = Provider.of(context, listen: false).totalTabs; + final ppmProvider = Provider.of(context, listen: false); + int totalTabs = ppmProvider.totalTabs; int currentIndex = totalTabs == 4 ? 2 : 1; return ListView.separated( itemCount: widget.models!.length + 1, @@ -37,27 +39,30 @@ class _PpmCalibrationToolsFormState extends State { separatorBuilder: (cxt, index) => 16.height, itemBuilder: (context, index) { if (index == widget.models!.length) { - return AppFilledButton( - label: "Add More Calibration Tools".addTranslation, - maxWidth: true, - textColor: AppColor.black10, - buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, - icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), - showIcon: true, - onPressed: () async { - if (widget.models?.isNotEmpty ?? false) { - if (widget.models!.last.asset?.id == null) { - await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.assetNumber}"); - return; + return Visibility( + visible: !ppmProvider.isReadOnly, + child: AppFilledButton( + label: "Add More Calibration Tools".addTranslation, + maxWidth: true, + textColor: AppColor.black10, + buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, + icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), + showIcon: true, + onPressed: () async { + if (widget.models?.isNotEmpty ?? false) { + if (widget.models!.last.asset?.id == null) { + await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.assetNumber}"); + return; + } + if (widget.models!.last.calibrationDateOfTesters == null) { + await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.date}"); + return; + } } - if (widget.models!.last.calibrationDateOfTesters == null) { - await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.date}"); - return; - } - } - widget.models!.add(PreventiveVisitCalibrations(id: 0)); - setState(() {}); - }, + widget.models!.add(PreventiveVisitCalibrations(id: 0)); + setState(() {}); + }, + ), ); } PreventiveVisitCalibrations model = widget.models![index]; @@ -68,48 +73,51 @@ class _PpmCalibrationToolsFormState extends State { borderRadius: BorderRadius.circular(20), boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - (index == 0 ? "$currentIndex /$totalTabs . Calibration Tools" : "").heading5(context), - "trash".toSvgAsset(height: 20, width: 15).onPress(() { - widget.models!.remove(model); + child: IgnorePointer( + ignoring:ppmProvider.isReadOnly, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + (index == 0 ? "$currentIndex /$totalTabs . Calibration Tools" : "").heading5(context), + "trash".toSvgAsset(height: 20, width: 15).onPress(() { + widget.models!.remove(model); + setState(() {}); + }), + ], + ), + 16.height, + CalibrationToolAssetPicker( + initialValue: model.asset?.id == null ? null : Lookup(id: model.asset?.id?.toInt(), name: model.asset?.assetNumber ?? ""), + hospitalId: userProvider.user!.clientId, + onPick: (asset) { + model.asset = Asset(id: asset.id, assetNumber: asset.assetNumber, assetSerialNo: asset.assetSerialNo); + setState(() {}); + }, + ), + 12.height, + if (model.asset?.assetNumber != null) + Text("Asset Number: ${model.asset?.assetNumber?.cleanupWhitespace.capitalizeFirstOfEach}", style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120)), + // if (model.assetName != null) Text("Asset Name: ${model.assetName?.cleanupWhitespace.capitalizeFirstOfEach}", style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120)), + if (model.asset?.assetSerialNo != null) + Text("Asset Serial No: ${model.asset?.assetSerialNo?.cleanupWhitespace.capitalizeFirstOfEach}", style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120)), + 12.height, + ADatePicker( + label: context.translation.calibrationDate, + date: DateTime.tryParse(model.calibrationDateOfTesters ?? ""), + from: DateTime.now().subtract(const Duration(days: 90)), + backgroundColor: context.isDark ? AppColor.neutral50 : AppColor.neutral100, + withBorder: false, + hideShadow: true, + onDatePicker: (date) { + model.calibrationDateOfTesters = date.toIso8601String(); setState(() {}); - }), - ], - ), - 16.height, - CalibrationToolAssetPicker( - initialValue: model.asset?.id == null ? null : Lookup(id: model.asset?.id?.toInt(), name: model.asset?.assetNumber ?? ""), - hospitalId: userProvider.user!.clientId, - onPick: (asset) { - model.asset = Asset(id: asset.id, assetNumber: asset.assetNumber, assetSerialNo: asset.assetSerialNo); - setState(() {}); - }, - ), - 12.height, - if (model.asset?.assetNumber != null) - Text("Asset Number: ${model.asset?.assetNumber?.cleanupWhitespace.capitalizeFirstOfEach}", style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120)), - // if (model.assetName != null) Text("Asset Name: ${model.assetName?.cleanupWhitespace.capitalizeFirstOfEach}", style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120)), - if (model.asset?.assetSerialNo != null) - Text("Asset Serial No: ${model.asset?.assetSerialNo?.cleanupWhitespace.capitalizeFirstOfEach}", style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120)), - 12.height, - ADatePicker( - label: context.translation.calibrationDate, - date: DateTime.tryParse(model.calibrationDateOfTesters ?? ""), - from: DateTime.now().subtract(const Duration(days: 90)), - backgroundColor: context.isDark ? AppColor.neutral50 : AppColor.neutral100, - withBorder: false, - hideShadow: true, - onDatePicker: (date) { - model.calibrationDateOfTesters = date.toIso8601String(); - setState(() {}); - }, - ), - ], + }, + ), + ], + ), ), ); }, diff --git a/lib/views/pages/user/ppm/update_ppm/ppm_external_details_form.dart b/lib/views/pages/user/ppm/update_ppm/ppm_external_details_form.dart index 72aba1aa..8fb7db23 100644 --- a/lib/views/pages/user/ppm/update_ppm/ppm_external_details_form.dart +++ b/lib/views/pages/user/ppm/update_ppm/ppm_external_details_form.dart @@ -237,6 +237,8 @@ // } import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/ppm_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart'; @@ -289,20 +291,23 @@ class _PpmExternalDetailsFormState extends State { @override Widget build(BuildContext context) { - print("widget.models!.length:${widget.models!.length}"); + final ppmProvider = Provider.of(context, listen: false); return ListView.builder( itemCount: widget.models!.length + 1, padding: const EdgeInsets.all(16), itemBuilder: (context, index) { if (index == widget.models!.length) { - return AppFilledButton( - label: "Add More External Details".addTranslation, - maxWidth: true, - textColor: AppColor.black10, - buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, - icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), - showIcon: true, - onPressed: _addNewEntry, + return Visibility( + visible: !ppmProvider.isReadOnly, + child: AppFilledButton( + label: "Add More External Details".addTranslation, + maxWidth: true, + textColor: AppColor.black10, + buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, + icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), + showIcon: true, + onPressed: _addNewEntry, + ), ); } // return !isLoading @@ -336,10 +341,12 @@ class ExternalDetailItem extends StatefulWidget { class _ExternalDetailItemState extends State { TextEditingController? controller; + PpmProvider? _ppmProvider; @override void initState() { controller = TextEditingController(text: widget.model.workingHours != null ? widget.model.workingHours.toString() : ''); + _ppmProvider= Provider.of(context,listen:false); super.initState(); } @@ -353,148 +360,151 @@ class _ExternalDetailItemState extends State { borderRadius: BorderRadius.circular(20), boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - (widget.index == 0 ? "1 /4 . External Details" : "").heading5(context), - Container( - height: 32, - width: 32, - padding: const EdgeInsets.all(6), - child: "trash".toSvgAsset(height: 20, width: 20), - ).onPress(() { - widget.onRemove(); - }), - ], - ), - 16.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.supplier, - initialValue: widget.model.supplier, - backgroundColor: AppColor.neutral100, - showAsBottomSheet: true, - showShadow: false, - onSelect: (supplier) { - if (supplier != null) { - setState(() { - widget.model.supplier = supplier; - }); - } - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - title: context.translation.supplierEngineer, - enabled: widget.model.supplier != null, - backgroundColor: AppColor.neutral100, - initialValue: widget.model.suppPerson, - staticData: widget.model.supplier?.suppPersons, - showAsBottomSheet: true, - showShadow: false, - onSelect: (suppPerson) { - if (suppPerson != null) { - widget.model.suppPerson = suppPerson; - } - }, - ), - 8.height, - Row( - mainAxisSize: MainAxisSize.min, - children: [ - ADatePicker( - label: context.translation.startTime, - hideShadow: true, - backgroundColor: AppColor.neutral100, - date: widget.model.startDateTime, - formatDateWithTime: true, - onDatePicker: (selectedDate) { - showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ).then((selectedTime) { - if (selectedTime != null) { - DateTime selectedDateTime = DateTime( - selectedDate.year, - selectedDate.month, - selectedDate.day, - selectedTime.hour, - selectedTime.minute, - ); - setState(() { - widget.model.startDateTime = selectedDateTime; - }); - widget.model.endDateTime = null; - controller?.clear(); - ServiceRequestUtils.calculateAndAssignWorkingHours( - startTime: widget.model.startDateTime, - endTime: widget.model.endDateTime, - workingHoursController: controller!, - updateModel: (hours) { - widget.model.workingHours = hours; - }, - ); - } + child: IgnorePointer( + ignoring: _ppmProvider!.isReadOnly, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + (widget.index == 0 ? "1 /4 . External Details" : "").heading5(context), + Container( + height: 32, + width: 32, + padding: const EdgeInsets.all(6), + child: "trash".toSvgAsset(height: 20, width: 20), + ).onPress(() { + widget.onRemove(); + }), + ], + ), + 16.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.supplier, + initialValue: widget.model.supplier, + backgroundColor: AppColor.neutral100, + showAsBottomSheet: true, + showShadow: false, + onSelect: (supplier) { + if (supplier != null) { + setState(() { + widget.model.supplier = supplier; }); - }, - ).expanded, - 8.width, - ADatePicker( - label: context.translation.endTime, - hideShadow: true, - backgroundColor: AppColor.neutral100, - date: widget.model.endDateTime, - formatDateWithTime: true, - onDatePicker: (selectedDate) { - showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ).then((selectedTime) { - if (selectedTime != null) { - DateTime selectedDateTime = DateTime( - selectedDate.year, - selectedDate.month, - selectedDate.day, - selectedTime.hour, - selectedTime.minute, - ); - if (widget.model.startDateTime != null && selectedDateTime.isBefore(widget.model.startDateTime!)) { - "End Date time must be greater than start date".showToast; - return; + } + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + title: context.translation.supplierEngineer, + enabled: widget.model.supplier != null, + backgroundColor: AppColor.neutral100, + initialValue: widget.model.suppPerson, + staticData: widget.model.supplier?.suppPersons, + showAsBottomSheet: true, + showShadow: false, + onSelect: (suppPerson) { + if (suppPerson != null) { + widget.model.suppPerson = suppPerson; + } + }, + ), + 8.height, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + ADatePicker( + label: context.translation.startTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: widget.model.startDateTime, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + setState(() { + widget.model.startDateTime = selectedDateTime; + }); + widget.model.endDateTime = null; + controller?.clear(); + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: widget.model.startDateTime, + endTime: widget.model.endDateTime, + workingHoursController: controller!, + updateModel: (hours) { + widget.model.workingHours = hours; + }, + ); } - setState(() { - widget.model.endDateTime = selectedDateTime; - }); - ServiceRequestUtils.calculateAndAssignWorkingHours( - startTime: widget.model.startDateTime, - endTime: widget.model.endDateTime, - workingHoursController: controller!, - updateModel: (hours) { - widget.model.workingHours = hours; - }, - ); - } - }); - }, - ).expanded, - ], - ), - 8.height, - AppTextFormField( - labelText: context.translation.workingHours, - backgroundColor: AppColor.neutral80, - controller: controller, - textAlign: TextAlign.center, - enable: false, - showShadow: false, - style: Theme.of(context).textTheme.titleMedium, - ), - 8.height, - ], + }); + }, + ).expanded, + 8.width, + ADatePicker( + label: context.translation.endTime, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: widget.model.endDateTime, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + if (widget.model.startDateTime != null && selectedDateTime.isBefore(widget.model.startDateTime!)) { + "End Date time must be greater than start date".showToast; + return; + } + setState(() { + widget.model.endDateTime = selectedDateTime; + }); + ServiceRequestUtils.calculateAndAssignWorkingHours( + startTime: widget.model.startDateTime, + endTime: widget.model.endDateTime, + workingHoursController: controller!, + updateModel: (hours) { + widget.model.workingHours = hours; + }, + ); + } + }); + }, + ).expanded, + ], + ), + 8.height, + AppTextFormField( + labelText: context.translation.workingHours, + backgroundColor: AppColor.neutral80, + controller: controller, + textAlign: TextAlign.center, + enable: false, + showShadow: false, + style: Theme.of(context).textTheme.titleMedium, + ), + 8.height, + ], + ), ), ); } diff --git a/lib/views/pages/user/ppm/update_ppm/ppm_pm_check_list_form.dart b/lib/views/pages/user/ppm/update_ppm/ppm_pm_check_list_form.dart index f8c55d5d..7d6e727e 100644 --- a/lib/views/pages/user/ppm/update_ppm/ppm_pm_check_list_form.dart +++ b/lib/views/pages/user/ppm/update_ppm/ppm_pm_check_list_form.dart @@ -32,6 +32,7 @@ class _PpmPmChecklistFormState extends State { @override Widget build(BuildContext context) { int totalTabs = Provider.of(context, listen: false).totalTabs; + final ppmProvider = Provider.of(context, listen: false); int currentIndex = totalTabs == 4 ? 4 : 3; List? list = widget.checkList ?? []; return (list.isEmpty) @@ -42,68 +43,71 @@ class _PpmPmChecklistFormState extends State { shrinkWrap: true, separatorBuilder: (cxt, index) => 12.height, itemBuilder: (context, index) { - return Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (index == 0) ...[ - "$currentIndex /$totalTabs . PM Checklist".heading5(context), - 16.height, + return IgnorePointer( + ignoring: ppmProvider.isReadOnly, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (index == 0) ...[ + "$currentIndex /$totalTabs . PM Checklist".heading5(context), + 16.height, + ], + AppTextFormField( + labelText: "Task".addTranslation, + labelStyle: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120, fontWeight: FontWeight.w500), + initialValue: list[index].instructionText?.text ?? "", + enable: false, + showShadow: false, + makeMultiLinesNull: true, + enableColor: AppColor.neutral100, + backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100, + // backgroundColor: context.isDark ? AppColor.neutral50 : null, + onChange: (text) { + list[index].taskComment = text; + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + showShadow: false, + backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100, + initialValue: list[index].taskStatus?.id == null ? null : Lookup(id: list[index].taskStatus?.id?.toInt(), name: list[index].taskStatus?.name), + title: context.translation.taskStatus, + onSelect: (value) { + if (value != null) { + list[index].taskStatus = Lookup(id: value.id, name: value.name, value: value.value); + } + }, + ), + 8.height, + AppTextFormField( + labelText: context.translation.measuredValue, + labelStyle: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120, fontWeight: FontWeight.w500), + initialValue: list[index].measuredValue ?? "", + // enable: false, + backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100, + showShadow: false, + onChange: (text) { + list[index].measuredValue = text; + }, + ), + 8.height, + AppTextFormField( + labelText: "Task Comment".addTranslation, + labelStyle: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120, fontWeight: FontWeight.w500), + initialValue: list[index].taskComment ?? "", + textInputType: TextInputType.multiline, + makeMultiLinesNull: true, + backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100, + showShadow: false, + onChange: (text) { + list[index].taskComment = text; + }, + ), ], - AppTextFormField( - labelText: "Task".addTranslation, - labelStyle: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120, fontWeight: FontWeight.w500), - initialValue: list[index].instructionText?.text ?? "", - enable: false, - showShadow: false, - makeMultiLinesNull: true, - enableColor: AppColor.neutral100, - backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100, - // backgroundColor: context.isDark ? AppColor.neutral50 : null, - onChange: (text) { - list[index].taskComment = text; - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - showShadow: false, - backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100, - initialValue: list[index].taskStatus?.id == null ? null : Lookup(id: list[index].taskStatus?.id?.toInt(), name: list[index].taskStatus?.name), - title: context.translation.taskStatus, - onSelect: (value) { - if (value != null) { - list[index].taskStatus = Lookup(id: value.id, name: value.name, value: value.value); - } - }, - ), - 8.height, - AppTextFormField( - labelText: context.translation.measuredValue, - labelStyle: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120, fontWeight: FontWeight.w500), - initialValue: list[index].measuredValue ?? "", - // enable: false, - backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100, - showShadow: false, - onChange: (text) { - list[index].measuredValue = text; - }, - ), - 8.height, - AppTextFormField( - labelText: "Task Comment".addTranslation, - labelStyle: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120, fontWeight: FontWeight.w500), - initialValue: list[index].taskComment ?? "", - textInputType: TextInputType.multiline, - makeMultiLinesNull: true, - backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral100, - showShadow: false, - onChange: (text) { - list[index].taskComment = text; - }, - ), - ], - ).toShadowContainer(context, showShadow: false, borderRadius: 20); + ).toShadowContainer(context, showShadow: false, borderRadius: 20), + ); }, ); } diff --git a/lib/views/pages/user/ppm/update_ppm/ppm_pm_kits_form.dart b/lib/views/pages/user/ppm/update_ppm/ppm_pm_kits_form.dart index fc3ffc94..516250a5 100644 --- a/lib/views/pages/user/ppm/update_ppm/ppm_pm_kits_form.dart +++ b/lib/views/pages/user/ppm/update_ppm/ppm_pm_kits_form.dart @@ -26,7 +26,8 @@ class PpmPMKitsForm extends StatefulWidget { class _PpmPMKitsFormState extends State { @override Widget build(BuildContext context) { - int totalTabs = Provider.of(context, listen: false).totalTabs; + final ppmProvider = Provider.of(context, listen: false); + int totalTabs = ppmProvider.totalTabs; int currentIndex = totalTabs == 4 ? 3 : 2; return ListView.builder( itemCount: widget.models!.length + 1, @@ -34,27 +35,30 @@ class _PpmPMKitsFormState extends State { padding: const EdgeInsets.only(left: 16, right: 16, top: 8, bottom: 16), itemBuilder: (context, index) { if (index == widget.models!.length) { - return AppFilledButton( - label: "Add More PM Kits".addTranslation, - maxWidth: true, - textColor: AppColor.black10, - buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, - icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), - showIcon: true, - onPressed: () async { - if (widget.models?.isNotEmpty ?? false) { - if (widget.models!.last.partCatalogItem?.partNumber == null) { - await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.partNumber}"); - return; + return Visibility( + visible: !ppmProvider.isReadOnly, + child: AppFilledButton( + label: "Add More PM Kits".addTranslation, + maxWidth: true, + textColor: AppColor.black10, + buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, + icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), + showIcon: true, + onPressed: () async { + if (widget.models?.isNotEmpty ?? false) { + if (widget.models!.last.partCatalogItem?.partNumber == null) { + await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.partNumber}"); + return; + } + if (widget.models!.last.partCatalogItem?.partName == null) { + await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.partName}"); + return; + } } - if (widget.models!.last.partCatalogItem?.partName == null) { - await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.partName}"); - return; - } - } - widget.models!.add(PreventiveVisitKits(id: 0)); - setState(() {}); - }, + widget.models!.add(PreventiveVisitKits(id: 0)); + setState(() {}); + }, + ), ); } final model = widget.models![index]; @@ -66,47 +70,50 @@ class _PpmPMKitsFormState extends State { borderRadius: BorderRadius.circular(20), boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - (index == 0 ? "$currentIndex /$totalTabs . PM Kits" : "").heading5(context), - Container( - height: 32, - width: 32, - padding: const EdgeInsets.all(6), - child: "trash".toSvgAsset(height: 20, width: 20), - ).onPress(() { - widget.models!.remove(model); + child: IgnorePointer( + ignoring: ppmProvider.isReadOnly, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + (index == 0 ? "$currentIndex /$totalTabs . PM Kits" : "").heading5(context), + Container( + height: 32, + width: 32, + padding: const EdgeInsets.all(6), + child: "trash".toSvgAsset(height: 20, width: 20), + ).onPress(() { + widget.models!.remove(model); + setState(() {}); + }), + ], + ), + 16.height, + AutoCompletePartsField( + assetId: widget.assetId, + clearAfterPick: false, + byName: true, + initialValue: model.partCatalogItem?.partName ?? "", + onPick: (part) { + model.partCatalogItem = PartCatalogItem(id: part.sparePart?.id, partNumber: part.sparePart?.partNo, partName: part.sparePart?.partName, oracleCode: part.sparePart?.oracleCode); + setState(() {}); + }, + ), + 8.height, + AutoCompletePartsField( + assetId: widget.assetId, + clearAfterPick: false, + byName: false, + initialValue: model.partCatalogItem?.partNumber ?? "", + onPick: (part) { + model.partCatalogItem = PartCatalogItem(id: part.sparePart?.id, partNumber: part.sparePart?.partNo, partName: part.sparePart?.partName, oracleCode: part.sparePart?.oracleCode); setState(() {}); - }), - ], - ), - 16.height, - AutoCompletePartsField( - assetId: widget.assetId, - clearAfterPick: false, - byName: true, - initialValue: model.partCatalogItem?.partName ?? "", - onPick: (part) { - model.partCatalogItem = PartCatalogItem(id: part.sparePart?.id, partNumber: part.sparePart?.partNo, partName: part.sparePart?.partName, oracleCode: part.sparePart?.oracleCode); - setState(() {}); - }, - ), - 8.height, - AutoCompletePartsField( - assetId: widget.assetId, - clearAfterPick: false, - byName: false, - initialValue: model.partCatalogItem?.partNumber ?? "", - onPick: (part) { - model.partCatalogItem = PartCatalogItem(id: part.sparePart?.id, partNumber: part.sparePart?.partNo, partName: part.sparePart?.partName, oracleCode: part.sparePart?.oracleCode); - setState(() {}); - }, - ), - ], + }, + ), + ], + ), ), ); }, diff --git a/lib/views/pages/user/ppm/update_ppm/update_ppm.dart b/lib/views/pages/user/ppm/update_ppm/update_ppm.dart index dc78915c..9188e24c 100644 --- a/lib/views/pages/user/ppm/update_ppm/update_ppm.dart +++ b/lib/views/pages/user/ppm/update_ppm/update_ppm.dart @@ -1,5 +1,4 @@ import 'dart:convert'; -import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -9,7 +8,6 @@ import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; -import 'package:test_sa/models/all_requests_and_count_model.dart'; import 'package:test_sa/models/plan_preventive_visit/plan_preventive_visit_model.dart'; import 'package:test_sa/models/ppm/ppm.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; @@ -44,8 +42,7 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { late PpmProvider ppmProvider; _onSubmit({required int status}) async { - - if(ppmProvider.validate()){ + if (ppmProvider.validate()) { showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); ppmProvider.planPreventiveVisit?.preventiveVisitAttachments = []; for (var item in ppmProvider.ppmPlanAttachments) { @@ -67,7 +64,7 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { }); await ppmProvider.updateVisitByEngineer(status: status).whenComplete(() { - if(status==1){ + if (status == 1) { AllRequestsProvider allRequestsProvider = Provider.of(context, listen: false); allRequestsProvider.reset(); allRequestsProvider.getAllRequests(context, typeTransaction: 4); @@ -78,15 +75,16 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { Navigator.pop(context); }); } - - } @override void initState() { + ppmProvider = Provider.of(context, listen: false); _planPreventiveVisit = widget.planPreventiveVisit; - initTabs(_planPreventiveVisit.typeOfService); + // WidgetsBinding.instance.addPostFrameCallback((_) { + initTabs(_planPreventiveVisit.typeOfService); + // }); super.initState(); } @@ -115,7 +113,12 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColor.neutral110, - appBar: DefaultAppBar(title: context.translation.preventiveMaintenance), + appBar: DefaultAppBar( + title: context.translation.preventiveMaintenance, + onWillPopScope:ppmProvider.isReadOnly?null: () { + _onSubmit(status: 0); + }, + ), key: _scaffoldKey, body: SafeArea( child: Column( @@ -158,6 +161,7 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { ), ), TabBarView( + physics: const NeverScrollableScrollPhysics(), children: [ WoInfoForm( planPreventiveVisit: _planPreventiveVisit, @@ -183,35 +187,72 @@ class _UpdatePpmState extends State with TickerProviderStateMixin { ).expanded, Row( children: [ - AppFilledButton( - buttonColor: AppColor.white60, - textColor: AppColor.neutral50, - onPressed: () { - _onSubmit(status: 0); - }, - label: context.translation.save, - ).expanded, - 16.width, - AppFilledButton( - onPressed: () { - if (tabIndex == 0) { - _onSubmit(status: 1); - return; - } - if (ppmProvider.totalTabs == _tabController!.index + 1) { - _onSubmit(status: 1); - } else { - _tabController?.animateTo(_tabController!.index + 1); + if (tabIndex == 1) ...[ + AppFilledButton( + buttonColor: _tabController!.index == 0 ? null : AppColor.background(context), + textColor: _tabController!.index == 0 ? null : AppColor.blueStatus(context), + showBorder: true, + disableButton: _tabController!.index == 0, + onPressed: () { + if (_tabController!.index == 0) { + return; + } + _tabController?.animateTo(_tabController!.index - 1); setState(() {}); - } - }, - label: tabIndex == 0 ? "Complete".addTranslation : ((ppmProvider.totalTabs == _tabController!.index + 1) ? "Complete".addTranslation : context.translation.next), - ).expanded, + return; + }, + label: context.translation.back, + ).expanded, + 8.width, + ], + if (!ppmProvider.isReadOnly) ...[ + AppFilledButton( + buttonColor: AppColor.white60, + textColor: AppColor.neutral50, + onPressed: () { + _onSubmit(status: 0); + }, + label: context.translation.save, + ).expanded, + 8.width, + AppFilledButton( + onPressed: () { + if (tabIndex == 0) { + _onSubmit(status: 1); + return; + } + if (ppmProvider.totalTabs == _tabController!.index + 1) { + _onSubmit(status: 1); + } else { + _tabController?.animateTo(_tabController!.index + 1); + setState(() {}); + } + }, + label: tabIndex == 0 ? "Complete".addTranslation : ((ppmProvider.totalTabs == _tabController!.index + 1) ? "Complete".addTranslation : context.translation.next), + ).expanded, + ] else ...[ + Visibility( + visible: tabIndex != 0, + child: AppFilledButton( + onPressed: () { + if(ppmProvider.totalTabs == _tabController!.index + 1){ + Navigator.pop(context); + return; + } + _tabController?.animateTo(_tabController!.index + 1); + setState(() {}); + }, + label:ppmProvider.totalTabs == _tabController!.index + 1? context.translation.close: context.translation.next, + ).expanded, + ), + ] ], ).toShadowContainer(context, showShadow: false, borderRadius: 0), ], ), ), - ); + ).handlePopScope(cxt: context, showPopUp:!ppmProvider.isReadOnly ,onSave: () { + _onSubmit(status: 0); + }); } } diff --git a/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart b/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart index a5e23ea4..7b4b32c7 100644 --- a/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart +++ b/lib/views/pages/user/ppm/update_ppm/wo_info_form.dart @@ -6,8 +6,15 @@ import 'package:test_sa/controllers/providers/api/ppm_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart'; +import 'package:test_sa/models/device/model_definition.dart'; +import 'package:test_sa/models/device/supplier.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; +import 'package:test_sa/models/new_models/building.dart'; +import 'package:test_sa/models/new_models/department.dart'; +import 'package:test_sa/models/new_models/floor.dart'; +import 'package:test_sa/models/new_models/room_model.dart'; +import 'package:test_sa/models/new_models/site.dart'; import 'package:test_sa/models/plan_preventive_visit/plan_preventive_visit_model.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/providers/ppm_asset_availability_provider.dart'; @@ -15,9 +22,11 @@ import 'package:test_sa/providers/ppm_electrical_safety_provider.dart'; import 'package:test_sa/providers/ppm_service_provider.dart'; import 'package:test_sa/providers/ppm_task_status_provider.dart'; import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart'; +import 'package:test_sa/views/widgets/bottom_sheets/asset_detail_bottom_sheet.dart'; import 'package:test_sa/views/widgets/date_and_time/date_picker.dart'; import 'package:test_sa/views/widgets/images/multi_image_picker.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart'; +import 'package:test_sa/models/device/asset.dart'; import '../../../../../models/lookup.dart'; import '../../../../../new_views/common_widgets/app_text_form_field.dart'; @@ -36,8 +45,6 @@ class WoInfoForm extends StatefulWidget { } class _WoInfoFormState extends State { - //TODO need to move this to provider ... - @override void initState() { WidgetsBinding.instance.addPostFrameCallback((_) async { @@ -56,218 +63,240 @@ class _WoInfoFormState extends State { double totalWorkingHours = widget.planPreventiveVisit.preventiveVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0; - totalWorkingHours = totalWorkingHours; return Consumer(builder: (context, ppmProvider, child) { + return ListView( padding: const EdgeInsets.only(left: 16, right: 16, top: 8, bottom: 16), children: [ - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (widget.planPreventiveVisit.visitStatus != null) - StatusLabel( - label: widget.planPreventiveVisit.visitStatus?.name, - textColor: AppColor.getRequestStatusTextColorByName(context, widget.planPreventiveVisit.visitStatus?.name), - backgroundColor: AppColor.getRequestStatusColorByName(context, widget.planPreventiveVisit.visitStatus?.name), - ), - 8.height, - widget.planPreventiveVisit.planName!.bodyText(context).custom(color: AppColor.black10), - 2.height, - '${context.translation.pmPlanNo}: ${widget.planPreventiveVisit.planNo}'.bodyText2(context).custom(color: AppColor.neutral120), - //need to add in translation it's suggestion from ahmed.. - 'Work Order Number: ${widget.planPreventiveVisit.visitNo}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.from}: ${widget.planPreventiveVisit.fromDate?.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.to}: ${widget.planPreventiveVisit.toDate?.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120), + IgnorePointer( + ignoring: ppmProvider.isReadOnly, + child: Column( + children: [ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (widget.planPreventiveVisit.visitStatus != null) + StatusLabel( + label: widget.planPreventiveVisit.visitStatus?.name, + textColor: AppColor.getRequestStatusTextColorByName(context, widget.planPreventiveVisit.visitStatus?.name), + backgroundColor: AppColor.getRequestStatusColorByName(context, widget.planPreventiveVisit.visitStatus?.name), + ), + 8.height, + widget.planPreventiveVisit.planName!.bodyText(context).custom(color: AppColor.black10), + 2.height, + '${context.translation.pmPlanNo}: ${widget.planPreventiveVisit.planNo}'.bodyText2(context).custom(color: AppColor.neutral120), + //need to add in translation it's suggestion from ahmed.. + 'Work Order Number: ${widget.planPreventiveVisit.visitNo}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.creationDate}: ${widget.planPreventiveVisit.creationDate?.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.closedDate}: ${widget.planPreventiveVisit.closedDate != null ? widget.planPreventiveVisit.closedDate?.toMonthYearFormat : '-'}' + .bodyText2(context) + .custom(color: AppColor.neutral120), - '${context.translation.nextPmDate}: ${widget.planPreventiveVisit.nextPMDate != null ? widget.planPreventiveVisit.nextPMDate!.toMonthYearFormat : '-'}' - .bodyText2(context) - .custom(color: AppColor.neutral120), - '${context.translation.assignEngineer}: ${widget.planPreventiveVisit.assignedEmployee?.userName ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.executionTimeFrame}: ${widget.planPreventiveVisit.executionTimeFrame ?? ""} days'.bodyText2(context).custom(color: AppColor.neutral120), - ], - ).toShadowContainer(context), - 12.height, - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - widget.planPreventiveVisit.assetName!.bodyText(context).custom(color: AppColor.black10), - "info_icon".toSvgAsset(height: 17, width: 17), - ], - ), - 2.height, - '${context.translation.assetNo}: ${widget.planPreventiveVisit.asset?.assetNumber}'.bodyText2(context).custom(color: AppColor.neutral120), - '${context.translation.model}: ${widget.planPreventiveVisit.model}'.bodyText2(context).custom(color: AppColor.neutral120), - ], - ).toShadowContainer(context), + '${context.translation.nextPmDate}: ${widget.planPreventiveVisit.nextPMDate != null ? widget.planPreventiveVisit.nextPMDate!.toMonthYearFormat : '-'}' + .bodyText2(context) + .custom(color: AppColor.neutral120), + '${context.translation.assignEngineer}: ${widget.planPreventiveVisit.assignedEmployee?.userName ?? ""}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.executionTimeFrame}: ${widget.planPreventiveVisit.executionTimeFrame ?? ""} days'.bodyText2(context).custom(color: AppColor.neutral120), + ], + ).toShadowContainer(context), + 12.height, + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + widget.planPreventiveVisit.assetName!.bodyText(context).custom(color: AppColor.black10), + "info_icon".toSvgAsset(height: 17, width: 17).onPress( + () { + // There is only limited information for asset is returned from backend to show all info need to return the whole model from backend... + showModalBottomSheet( + context: context, + isScrollControlled: true, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + clipBehavior: Clip.antiAliasWithSaveLayer, + builder: (BuildContext context) => _buildAssetDetailBottomSheet(context), + ); + }, + ) + ], + ), + 2.height, + '${context.translation.assetNo}: ${widget.planPreventiveVisit.asset?.assetNumber}'.bodyText2(context).custom(color: AppColor.neutral120), + '${context.translation.model}: ${widget.planPreventiveVisit.model}'.bodyText2(context).custom(color: AppColor.neutral120), + ], + ).toShadowContainer(context), - // SingleItemDropDownMenu( - // context: context, - // initialValue: - // widget.planPreventiveVisit.visitStatus?.id == null ? null : Lookup(name: widget.planPreventiveVisit.visitStatus?.name ?? "", id: widget.planPreventiveVisit.visitStatus?.id?.toInt()), - // title: context.translation.ppmVisit, - // onSelect: (value) { - // if (value?.value == 4) { - // "Status cannot be change to ${value?.name}.".addTranslation.showToast; - // setState(() {}); - // return; - // } - // - // if (value != null) { - // widget.planPreventiveVisit.visitStatus?.name = value.name; - // widget.planPreventiveVisit.visitStatus?.id = value.id; - // } - // }, - // ), + // SingleItemDropDownMenu( + // context: context, + // initialValue: + // widget.planPreventiveVisit.visitStatus?.id == null ? null : Lookup(name: widget.planPreventiveVisit.visitStatus?.name ?? "", id: widget.planPreventiveVisit.visitStatus?.id?.toInt()), + // title: context.translation.ppmVisit, + // onSelect: (value) { + // if (value?.value == 4) { + // "Status cannot be change to ${value?.name}.".addTranslation.showToast; + // setState(() {}); + // return; + // } + // + // if (value != null) { + // widget.planPreventiveVisit.visitStatus?.name = value.name; + // widget.planPreventiveVisit.visitStatus?.id = value.id; + // } + // }, + // ), - // SingleItemDropDownMenu( - // context: context, - // initialValue: widget.planPreventiveVisit.deviceStatusId == null ? null : Lookup(name: widget.model.deviceStatusName ?? "", id: widget.model.deviceStatusId?.toInt()), - // title: context.translation.deviceStatus, - // onSelect: (value) { - // if (value != null) { - // widget.planPreventiveVisit.deviceStatusId = value.id; - // widget.planPreventiveVisit.deviceStatusName = value.name; - // } - // }, - // ), - 8.height, - Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - //TODO Ahmed need to provide look up value.... - - SingleItemDropDownMenu( - context: context, - showShadow: false, - initialValue: widget.planPreventiveVisit.taskStatus == null ? null : Lookup(name: widget.planPreventiveVisit.taskStatus?.name ?? "", id: widget.planPreventiveVisit.taskStatus?.id), - title: context.translation.pmTestResult, - backgroundColor: AppColor.neutral100, - onSelect: (value) { - if (value != null) { - widget.planPreventiveVisit.taskStatus = value; - } - }, - ), - 8.height, - ADatePicker( - label: context.translation.actualVisit, - hideShadow: true, - backgroundColor: AppColor.neutral100, - date: widget.planPreventiveVisit.acutalDateOfVisit, - formatDateWithTime: true, - onDatePicker: (selectedDate) { - showTimePicker( - context: context, - initialTime: TimeOfDay.now(), - ).then((selectedTime) { - if (selectedTime != null) { - DateTime selectedDateTime = DateTime( - selectedDate.year, - selectedDate.month, - selectedDate.day, - selectedTime.hour, - selectedTime.minute, - ); - setState(() { - widget.planPreventiveVisit.acutalDateOfVisit = selectedDateTime; - }); - } - }); - }, - ), - // SingleItemDropDownMenu( - // context: context, - // backgroundColor: AppColor.neutral100, - // initialValue: widget.planPreventiveVisit.safety?.id == null ? null : Lookup(name: widget.planPreventiveVisit.safety?.name ?? "", id: widget.planPreventiveVisit.safety?.id), - // title: context.translation.actualVisit, - // onSelect: (value) { - // if (value != null) { - // widget.planPreventiveVisit.safety = value; - // // widget.planPreventiveVisit.safety?.id = value.id; - // // widget.planPreventiveVisit.safety?.name = value.name; - // } - // }, - // ), + // SingleItemDropDownMenu( + // context: context, + // initialValue: widget.planPreventiveVisit.deviceStatusId == null ? null : Lookup(name: widget.model.deviceStatusName ?? "", id: widget.model.deviceStatusId?.toInt()), + // title: context.translation.deviceStatus, + // onSelect: (value) { + // if (value != null) { + // widget.planPreventiveVisit.deviceStatusId = value.id; + // widget.planPreventiveVisit.deviceStatusName = value.name; + // } + // }, + // ), + 8.height, + Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SingleItemDropDownMenu( + context: context, + showShadow: false, + initialValue: widget.planPreventiveVisit.taskStatus == null ? null : Lookup(name: widget.planPreventiveVisit.taskStatus?.name ?? "", id: widget.planPreventiveVisit.taskStatus?.id), + title: context.translation.pmTestResult, + backgroundColor: AppColor.neutral100, + onSelect: (value) { + if (value != null) { + widget.planPreventiveVisit.taskStatus = value; + } + }, + ), + 8.height, + ADatePicker( + label: context.translation.actualVisit, + hideShadow: true, + backgroundColor: AppColor.neutral100, + date: widget.planPreventiveVisit.acutalDateOfVisit, + formatDateWithTime: true, + onDatePicker: (selectedDate) { + showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ).then((selectedTime) { + if (selectedTime != null) { + DateTime selectedDateTime = DateTime( + selectedDate.year, + selectedDate.month, + selectedDate.day, + selectedTime.hour, + selectedTime.minute, + ); + setState(() { + widget.planPreventiveVisit.acutalDateOfVisit = selectedDateTime; + }); + } + }); + }, + ), + // SingleItemDropDownMenu( + // context: context, + // backgroundColor: AppColor.neutral100, + // initialValue: widget.planPreventiveVisit.safety?.id == null ? null : Lookup(name: widget.planPreventiveVisit.safety?.name ?? "", id: widget.planPreventiveVisit.safety?.id), + // title: context.translation.actualVisit, + // onSelect: (value) { + // if (value != null) { + // widget.planPreventiveVisit.safety = value; + // // widget.planPreventiveVisit.safety?.id = value.id; + // // widget.planPreventiveVisit.safety?.name = value.name; + // } + // }, + // ), - 8.height, - SingleItemDropDownMenu( - context: context, - backgroundColor: AppColor.neutral100, - showShadow: false, - initialValue: widget.planPreventiveVisit.safety?.id == null ? null : Lookup(name: widget.planPreventiveVisit.safety?.name ?? "", id: widget.planPreventiveVisit.safety?.id), - title: "Electrical Safety", - onSelect: (value) { - if (value != null) { - widget.planPreventiveVisit.safety = value; - } - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - backgroundColor: AppColor.neutral100, - showShadow: false, - initialValue: widget.planPreventiveVisit.assetAvailability == null - ? null - : Lookup(name: widget.planPreventiveVisit.assetAvailability?.name ?? "", id: widget.planPreventiveVisit.assetAvailability?.id), - title: "Asset Availability", - onSelect: (value) { - if (value != null) { - widget.planPreventiveVisit.assetAvailability = value; - } - }, - ), - 8.height, - SingleItemDropDownMenu( - context: context, - backgroundColor: AppColor.neutral100, - showShadow: false, - initialValue: widget.planPreventiveVisit.typeOfService == null - ? null - : Lookup(name: widget.planPreventiveVisit.typeOfService?.name ?? "", id: widget.planPreventiveVisit.typeOfService?.id?.toInt()), - title: context.translation.typeOfPm, - onSelect: (value) { - if (value != null) { - widget.planPreventiveVisit.typeOfService = value; - if (widget.planPreventiveVisit.typeOfService?.id == 66) { - ppmProvider.totalTabs = 4; - } else { - ppmProvider.totalTabs = 3; - } - widget.onTypeOfServiceChange!(value); - } - }, - ), - 8.height, - _timerWidget(context, totalWorkingHours), - 8.height, - AppTextFormField( - labelText: context.translation.callComments, - backgroundColor: AppColor.neutral100, - showShadow: false, - initialValue: (widget.planPreventiveVisit.comments ?? "").toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.titleMedium, - onChange: (value) { - widget.planPreventiveVisit.comments = value; - }, - ), - 16.height, - MultiFilesPicker( - label: context.translation.attachments, - files: ppmProvider.ppmPlanAttachments, - buttonColor: AppColor.black10, - onlyImages: false, - buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), - ), - ], - ).toShadowContainer(context), + 8.height, + SingleItemDropDownMenu( + context: context, + backgroundColor: AppColor.neutral100, + showShadow: false, + initialValue: widget.planPreventiveVisit.safety?.id == null ? null : Lookup(name: widget.planPreventiveVisit.safety?.name ?? "", id: widget.planPreventiveVisit.safety?.id), + title: "Electrical Safety", + onSelect: (value) { + if (value != null) { + widget.planPreventiveVisit.safety = value; + } + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + backgroundColor: AppColor.neutral100, + showShadow: false, + initialValue: widget.planPreventiveVisit.assetAvailability == null + ? null + : Lookup(name: widget.planPreventiveVisit.assetAvailability?.name ?? "", id: widget.planPreventiveVisit.assetAvailability?.id), + title: "Asset Availability", + onSelect: (value) { + if (value != null) { + widget.planPreventiveVisit.assetAvailability = value; + } + }, + ), + 8.height, + SingleItemDropDownMenu( + context: context, + backgroundColor: AppColor.neutral100, + showShadow: false, + initialValue: widget.planPreventiveVisit.typeOfService == null + ? null + : Lookup(name: widget.planPreventiveVisit.typeOfService?.name ?? "", id: widget.planPreventiveVisit.typeOfService?.id?.toInt()), + title: context.translation.typeOfPm, + onSelect: (value) { + if (value != null) { + widget.planPreventiveVisit.typeOfService = value; + if (widget.planPreventiveVisit.typeOfService?.id == 66) { + ppmProvider.totalTabs = 4; + } else { + ppmProvider.totalTabs = 3; + } + widget.onTypeOfServiceChange!(value); + } + }, + ), + 8.height, + _timerWidget(context, totalWorkingHours), + 8.height, + AppTextFormField( + labelText: context.translation.comment, + backgroundColor: AppColor.neutral100, + showShadow: false, + initialValue: (widget.planPreventiveVisit.comments ?? "").toString(), + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleMedium, + onChange: (value) { + widget.planPreventiveVisit.comments = value; + }, + ), + 16.height, + MultiFilesPicker( + label: context.translation.attachments, + files: ppmProvider.ppmPlanAttachments, + buttonColor: AppColor.black10, + onlyImages: false, + buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), + ), + ], + ).toShadowContainer(context), + ], + ), + ), //TODO need to check this also... // ESignature( // title: context.translation.nurseSignature, @@ -292,6 +321,33 @@ class _WoInfoFormState extends State { }); } + _buildAssetDetailBottomSheet(BuildContext context) { + PlanPreventiveVisit model = widget.planPreventiveVisit; + Asset asset = Asset( + id: model.asset?.id, + assetSerialNo: model.asset?.assetSerialNo, + assetNumber: model.asset?.assetNumber, + building: Building(name: model.buildingName), + floor: Floor(name: model.floorName), + site: Site(custName: model.siteName), + supplier: Supplier(suppliername: model.supplierName), + modelDefinition: ModelDefinition(modelName: model.model, manufacturerName: model.manufacturer), + room: Rooms(value: int.tryParse(model.roomName??'')), + department: Department(departmentName: model.departmentName), + ); + return AssetDetailBottomSheet(asset); + } + + // Future getAssetById () async { + // Asset asset = Asset(); + // AssetProvider _assetProvider = Provider.of(context, listen: false); + // if(widget.planPreventiveVisit.asset!=null){ + // AssetByIdModel ?assetByIdModel = await _assetProvider.getAssetById(widget.planPreventiveVisit.asset!.id!.toInt(), context.translation); + // asss + // } + // return asset; + // } + Widget _timerWidget(BuildContext context, double totalWorkingHours) { return Column( children: [ diff --git a/lib/views/pages/user/requests/pending_requests_screen.dart b/lib/views/pages/user/requests/pending_requests_screen.dart index 4ae44fa5..ee99a490 100644 --- a/lib/views/pages/user/requests/pending_requests_screen.dart +++ b/lib/views/pages/user/requests/pending_requests_screen.dart @@ -18,7 +18,7 @@ class PendingServiceRequestScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: DefaultAppBar(title: "Pending Requests (${pendingAssetServiceRequest.details!.length})"), + appBar: DefaultAppBar(title: "Pending WOs (${pendingAssetServiceRequest.details!.length})"), body: ListView.separated( itemCount: pendingAssetServiceRequest.details!.length, padding: const EdgeInsets.all(16), diff --git a/lib/views/widgets/bottom_sheets/asset_detail_bottom_sheet.dart b/lib/views/widgets/bottom_sheets/asset_detail_bottom_sheet.dart index 1b75aeae..474ae1a3 100644 --- a/lib/views/widgets/bottom_sheets/asset_detail_bottom_sheet.dart +++ b/lib/views/widgets/bottom_sheets/asset_detail_bottom_sheet.dart @@ -48,9 +48,9 @@ class AssetDetailBottomSheet extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ "${context.translation.assetNo}: ${asset!.assetNumber}".bodyText(context), - "${context.translation.modelName}: ${asset!.modelDefinition!.modelName}".bodyText(context), + "${context.translation.modelName}: ${asset!.modelDefinition?.modelName}".bodyText(context), "${context.translation.supplier}: ${asset!.supplier?.suppliername?.cleanupWhitespace.capitalizeFirstOfEach ?? "-"}".bodyText(context), - "${context.translation.manufacture}: ${asset!.modelDefinition!.manufacturerName?.cleanupWhitespace.capitalizeFirstOfEach}".bodyText(context), + "${context.translation.manufacture}: ${asset!.modelDefinition?.manufacturerName?.cleanupWhitespace.capitalizeFirstOfEach}".bodyText(context), //"${context.translation.location}: ${assetModel.site.custName?.cleanupWhitespace?.capitalizeFirstOfEach}".bodyText(context), ], ).expanded, diff --git a/lib/views/widgets/bottom_sheets/pending_request_bottom_sheet.dart b/lib/views/widgets/bottom_sheets/pending_request_bottom_sheet.dart index f22c2d1b..84b98782 100644 --- a/lib/views/widgets/bottom_sheets/pending_request_bottom_sheet.dart +++ b/lib/views/widgets/bottom_sheets/pending_request_bottom_sheet.dart @@ -25,7 +25,7 @@ class PendingRequestBottomSheet extends StatelessWidget { "Alert!".heading4(context), 12.height, Text( - "${pendingAssetServiceRequest.details!.length} pending service requests found", + "${pendingAssetServiceRequest.details!.length} pending corrective maintenance found", style: TextStyle( fontSize: 16.toScreenWidth, fontWeight: FontWeight.w500, diff --git a/lib/views/widgets/equipment/asset_picker.dart b/lib/views/widgets/equipment/asset_picker.dart index 113a5876..eb861088 100644 --- a/lib/views/widgets/equipment/asset_picker.dart +++ b/lib/views/widgets/equipment/asset_picker.dart @@ -19,6 +19,7 @@ class AssetPicker extends StatelessWidget { final bool showAssetInfo; final Color? borderColor; final Color? buttonColor; + Color? backgroundColor; final bool forPPM; final bool showLoading; final bool multiSelection; @@ -33,6 +34,7 @@ class AssetPicker extends StatelessWidget { this.onAssetRemove, this.borderColor, this.buttonColor, + this.backgroundColor, this.showAssetInfo = true, this.multiSelection = false, this.forPPM = false, @@ -53,7 +55,7 @@ class AssetPicker extends StatelessWidget { height: 50, alignment: Alignment.center, decoration: BoxDecoration( - color: buttonColor ?? AppColor.blueStatus(context), + color: buttonColor ?? backgroundColor?? AppColor.blueStatus(context), borderRadius: BorderRadius.circular(10), // boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], ), diff --git a/lib/views/widgets/equipment/commissioning_status_buttons.dart b/lib/views/widgets/equipment/commissioning_status_buttons.dart index 67931dc8..ba6e59fe 100644 --- a/lib/views/widgets/equipment/commissioning_status_buttons.dart +++ b/lib/views/widgets/equipment/commissioning_status_buttons.dart @@ -54,7 +54,7 @@ class _CommissioningStatusButtonsState extends State return Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - context.translation.equipmentStatus.heading5(context).paddingOnly(start: 16, end: 16), + context.translation.assetStatus.heading5(context).paddingOnly(start: 16, end: 16), 8.height, Consumer( builder: (context, snapshot, _) { diff --git a/lib/views/widgets/gas_refill/gas_refill_item.dart b/lib/views/widgets/gas_refill/gas_refill_item.dart index 4cf4af7d..e8551865 100644 --- a/lib/views/widgets/gas_refill/gas_refill_item.dart +++ b/lib/views/widgets/gas_refill/gas_refill_item.dart @@ -41,7 +41,7 @@ class GasRefillItem extends StatelessWidget { ), 8.height, context.translation.gasRefillRequest.heading5(context), - '${context.translation.gasType}: ${item.gazRefillDetails![0].gasType!.name}'.bodyText(context), + '${context.translation.gasType}: ${item.gasRefillDetails![0].gasType!.name}'.bodyText(context), '${context.translation.site}: ${item.site!.name}'.bodyText(context), 8.height, Row( diff --git a/lib/views/widgets/images/multi_image_picker.dart b/lib/views/widgets/images/multi_image_picker.dart index 1fe5a186..3608aa5b 100644 --- a/lib/views/widgets/images/multi_image_picker.dart +++ b/lib/views/widgets/images/multi_image_picker.dart @@ -18,6 +18,7 @@ class MultiFilesPicker extends StatefulWidget { final String label; final bool error; final List files; + final List attachment ; final bool enabled, onlyImages; double? buttonHeight; Widget? buttonIcon; @@ -28,6 +29,7 @@ class MultiFilesPicker extends StatefulWidget { MultiFilesPicker( {Key? key, this.files = const [], + this.attachment = const [], required this.label, this.error = false, this.buttonHeight, @@ -49,17 +51,19 @@ class _MultiFilesPickerState extends State { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - AppDashedButton( - title: widget.label, - height: widget.buttonHeight, - buttonColor: widget.buttonColor, - icon: widget.buttonIcon, - onPressed: (widget.enabled == false) - ? () {} - : widget.showAsGrid - ? showFileSourceSheet - : onFilePicker), - 16.height, + if(widget.enabled)...[ + AppDashedButton( + title: widget.label, + height: widget.buttonHeight, + buttonColor: widget.buttonColor, + icon: widget.buttonIcon, + onPressed: (widget.enabled == false) + ? () {} + : widget.showAsGrid + ? showFileSourceSheet + : onFilePicker), + 16.height, + ], if (widget.files.isNotEmpty) Wrap( spacing: 8.toScreenWidth, @@ -123,10 +127,10 @@ class _MultiFilesPickerState extends State { "Attach File".heading4(context), 12.height, GridView( - padding: EdgeInsets.all(0), + padding: const EdgeInsets.all(0), shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12), children: [ gridItem(Icons.camera_enhance_rounded, context.translation.pickFromCamera).onPress(() => Navigator.of(context).pop(ImageSource.camera)), gridItem(Icons.image_rounded, context.translation.pickFromGallery).onPress(() => Navigator.of(context).pop(ImageSource.gallery)), @@ -141,38 +145,34 @@ class _MultiFilesPickerState extends State { ).paddingAll(21), )) as ImageSource; - if (source == null) return; - 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.files.add(fileImage); - if (widget.onChange != null) { - widget.onChange!(widget.files); - } - setState(() {}); + widget.files.add(fileImage); + if (widget.onChange != null) { + widget.onChange!(widget.files); } - } + setState(() {}); + } } Widget gridItem(IconData iconData, String title) { return Container( - padding: EdgeInsets.all(12), + padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), - border: Border.all(color: Color(0xffF1F1F1), width: 1), + border: Border.all(color: const Color(0xffF1F1F1), width: 1), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Icon(iconData, color: Color(0xff7D859A), size: 36), + Icon(iconData, color: const Color(0xff7D859A), size: 36), Text( title, - style: TextStyle(fontSize: 12, fontWeight: FontWeight.w500), + style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500), ), ], ), @@ -285,3 +285,295 @@ class _MultiFilesPickerState extends State { setState(() {}); } } + + + + + +class AttachmentModel { + int id =0; + File ? file; + AttachmentModel(this.id,this.file); + + factory AttachmentModel.fromJson(Map json) { + return AttachmentModel( + json['id'] ?? 0, + json['file'] != null ? File(json['file']) : null, + ); + } + + Map toJson() { + return { + 'id': id, + 'file': file?.path, + }; + } + + +} + +class AttachmentPicker extends StatefulWidget { + final String label; + final bool error; + final List attachment ; + final bool enabled, onlyImages; + double? buttonHeight; + Widget? buttonIcon; + Color? buttonColor; + final Function(List)? onChange; + final bool showAsGrid; + + AttachmentPicker( + {Key? key, + this.attachment = const [], + required this.label, + this.error = false, + this.buttonHeight, + this.buttonIcon, + this.enabled = true, + this.onlyImages = false, + this.onChange, + this.showAsGrid = false, + this.buttonColor}) + : super(key: key); + + @override + State createState() => _AttachmentPickerState(); +} + +class _AttachmentPickerState extends State { + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AppDashedButton( + title: widget.label, + height: widget.buttonHeight, + buttonColor: widget.buttonColor, + icon: widget.buttonIcon, + onPressed: (widget.enabled == false) + ? () {} + : widget.showAsGrid + ? showFileSourceSheet + : onFilePicker), + 16.height, + if (widget.attachment.isNotEmpty) + Wrap( + spacing: 8.toScreenWidth, + children: List.generate( + widget.attachment.length, + (index) { + File image = widget.attachment[index].file!; + return MultiFilesPickerItem( + file: image, + enabled: widget.enabled, + onRemoveTap: (image) { + if (!widget.enabled) { + return; + } + widget.attachment.remove(image); + if (widget.onChange != null) { + widget.onChange!(widget.attachment); + } + setState(() {}); + }, + ); + }, + ), + ), + ], + ); + } + + fromFilePicker() async { + FilePickerResult? result = await FilePicker.platform.pickFiles( + type: FileType.custom, + allowMultiple: true, + allowedExtensions: widget.onlyImages ? ['jpg', 'jpeg', 'png'] : ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xlsx', 'pptx'], + ); + if (result != null) { + for (var path in result.paths) { + widget.attachment.add(AttachmentModel(0, File(path!))); + } + setState(() {}); + } + } + + void showFileSourceSheet() async { + if (widget.attachment.length >= 5) { + Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5); + return; + } + + ImageSource source = (await showModalBottomSheet( + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + clipBehavior: Clip.antiAliasWithSaveLayer, + builder: (BuildContext context) => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Attach File".heading4(context), + 12.height, + GridView( + padding: const EdgeInsets.all(0), + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12), + children: [ + gridItem(Icons.camera_enhance_rounded, context.translation.pickFromCamera).onPress(() => Navigator.of(context).pop(ImageSource.camera)), + gridItem(Icons.image_rounded, context.translation.pickFromGallery).onPress(() => Navigator.of(context).pop(ImageSource.gallery)), + gridItem(Icons.file_present_rounded, context.translation.pickFromFiles).onPress(() async { + await fromFilePicker(); + Navigator.pop(context); + }), + ], + ), + 12.height, + ], + ).paddingAll(21), + )) as ImageSource; + + final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800); + + if (pickedFile != null) { + File fileImage = File(pickedFile.path); + widget.attachment.add(AttachmentModel(0, fileImage)); + if (widget.onChange != null) { + widget.onChange!(widget.attachment); + } + setState(() {}); + } + } + + Widget gridItem(IconData iconData, String title) { + return Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: const Color(0xffF1F1F1), width: 1), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Icon(iconData, color: const Color(0xff7D859A), size: 36), + Text( + title, + style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500), + ), + ], + ), + ); + } + + onFilePicker() async { + if (widget.attachment.length >= 5) { + Fluttertoast.showToast(msg: context.translation.maxImagesNumberIs5); + return; + } + ImageSource? source = await showModalBottomSheet( + context: context, + builder: (BuildContext context) { + Widget listCard({required String icon, required String label, required VoidCallback onTap}){ + return GestureDetector( + onTap: onTap, + child: Container( + constraints: BoxConstraints(minWidth: 111.toScreenWidth,minHeight: 111.toScreenHeight), + padding: EdgeInsets.symmetric(horizontal: 12.toScreenWidth,vertical: 12.toScreenHeight), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + border: Border.all(width: 1,color:AppColor.white70) + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + icon.toSvgAsset(), + 24.height, + label.bodyText2(context).custom(color: AppColor.black20), + ], + ), + ), + ); + } + return Container( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + listCard( + icon: 'camera_icon', + label: '${context.translation.open}\n${context.translation.camera}', + onTap: () { + Navigator.of(context).pop(ImageSource.camera); + }, + ), + listCard( + icon: 'gallery_icon', + label: '${context.translation.open}\n${context.translation.gallery}', + onTap: () { + Navigator.of(context).pop(ImageSource.gallery); + }, + ), + listCard( + icon: 'file_icon', + label: '${context.translation.open}\n${context.translation.files}', + onTap: () async { + await fromFilePicker(); + Navigator.pop(context); + }, + ), + ], + ), + ); + }, + ); + // ImageSource source = await showDialog( + // context: context, + // builder: (dialogContext) => CupertinoAlertDialog( + // actions: [ + // TextButton( + // child: Text(context.translation.pickFromCamera), + // onPressed: () { + // Navigator.of(dialogContext).pop(ImageSource.camera); + // }, + // ), + // TextButton( + // child: Text(context.translation.pickFromGallery), + // onPressed: () { + // Navigator.of(dialogContext).pop(ImageSource.gallery); + // }, + // ), + // TextButton( + // child: Text(context.translation.pickFromFiles), + // onPressed: () async { + // await fromFilePicker(); + // Navigator.pop(context); + // }, + // ), + // ], + // ), + // ); + if (source == null) return; + + final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800); + + if (pickedFile != null) { + File fileImage = File(pickedFile.path); + widget.attachment.add(AttachmentModel(0, fileImage)); + if (widget.onChange != null) { + widget.onChange!(widget.attachment); + } + setState(() {}); + } + + setState(() {}); + } +} diff --git a/lib/views/widgets/parts/auto_complete_parts_field.dart b/lib/views/widgets/parts/auto_complete_parts_field.dart index 1ce09558..bf9703cf 100644 --- a/lib/views/widgets/parts/auto_complete_parts_field.dart +++ b/lib/views/widgets/parts/auto_complete_parts_field.dart @@ -32,6 +32,7 @@ class _AutoCompletePartsFieldState extends State { @override void initState() { + print('initial value i got is ${widget.initialValue}'); _controller = TextEditingController(text: widget.initialValue); super.initState(); } diff --git a/lib/views/widgets/status/assistant_employee_menu.dart b/lib/views/widgets/status/assistant_employee_menu.dart index 259d38cc..01d66f8a 100644 --- a/lib/views/widgets/status/assistant_employee_menu.dart +++ b/lib/views/widgets/status/assistant_employee_menu.dart @@ -18,8 +18,9 @@ class AssistantEmployeeMenu extends StatefulWidget { final String? title; // Now nullable final bool enable; final bool showAsBottomSheet; + final bool hideShadow; - AssistantEmployeeMenu({Key? key, required this.statuses, this.title, this.showAsBottomSheet = false, required this.onSelect, this.initialStatus, this.backgroundColor, this.enable = true}) + AssistantEmployeeMenu({Key? key, required this.statuses, this.title, this.showAsBottomSheet = false,this.hideShadow = false, required this.onSelect, this.initialStatus, this.backgroundColor, this.enable = true}) : super(key: key); @override @@ -74,7 +75,7 @@ class _SingleAssistantEmployeeMenuState extends State { decoration: BoxDecoration( color: widget.backgroundColor ?? (context.isDark ? AppColor.neutral50 : AppColor.neutral120), borderRadius: BorderRadius.circular(10), - boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], + boxShadow: widget.hideShadow ? null : [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], ), child: Stack( alignment: Alignment.center, 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 index 0dab25cc..5024585e 100644 --- a/lib/views/widgets/status/report/service_report_assistant_employee_menu.dart +++ b/lib/views/widgets/status/report/service_report_assistant_employee_menu.dart @@ -31,6 +31,7 @@ class ServiceReportAssistantEmployeeMenu extends StatelessWidget { initialStatus: initialValue, title: title, showAsBottomSheet: true, + hideShadow: true, statuses: menuProvider.assistantEmployees ?? [], backgroundColor: backgroundColor, // Provide an empty list if null diff --git a/pubspec.lock b/pubspec.lock index 402dbb06..4546b9fd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1213,6 +1213,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.2" + pie_chart: + dependency: "direct main" + description: + name: pie_chart + sha256: "58e6a46999ac938bfa1c3e5be414d6e149f037647197dca03ba3614324c12c82" + url: "https://pub.dev" + source: hosted + version: "5.4.0" pinput: dependency: "direct main" description: @@ -1506,22 +1514,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" - syncfusion_flutter_charts: - dependency: "direct main" - description: - name: syncfusion_flutter_charts - sha256: a755274a8786b200b7a05f7414168cd5858871db74d0f1de2e57b20a8aaeb7a4 - url: "https://pub.dev" - source: hosted - version: "26.2.14" - syncfusion_flutter_core: - dependency: transitive - description: - name: syncfusion_flutter_core - sha256: "6e67726b85812afc7105725a23620b876ab7f6b04b8410e211330ffb8c2cdbe8" - url: "https://pub.dev" - source: hosted - version: "26.2.14" synchronized: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 8cc4034f..2bcf8f5b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -79,11 +79,11 @@ dependencies: image_cropper: ^8.0.2 flutter_timezone: ^3.0.1 device_calendar: ^4.3.3 + pie_chart: ^5.4.0 badges: ^3.1.1 # buttons_tabbar: ^1.1.2 flutter_custom_month_picker: ^0.1.3 - syncfusion_flutter_charts: ^26.2.14 local_auth: ^2.3.0 google_api_availability: ^5.0.0 huawei_push: ^6.5.0+300