Merge branch 'refs/heads/demo_branch' into design_3.0_tm_module_task_flow

# Conflicts:
#	lib/controllers/api_routes/urls.dart
#	lib/extensions/widget_extensions.dart
#	lib/l10n/app_ar.arb
#	lib/l10n/app_en.arb
#	lib/new_views/pages/land_page/create_request-type_bottomsheet.dart
#	lib/new_views/pages/new_gas_refill_request_page.dart
#	lib/views/pages/user/gas_refill/request_gas_refill.dart
#	lib/views/widgets/equipment/asset_picker.dart
ai_enhancement_fcm_grouping
Sikander Saleem 1 year ago
commit e0902eddf7

@ -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

@ -2,6 +2,7 @@ class URLs {
URLs._(); URLs._();
static const String appReleaseBuildNumber = "14"; static const String appReleaseBuildNumber = "14";
// static const host1 = "https://atomsm.hmg.com"; // production url // static const host1 = "https://atomsm.hmg.com"; // production url
static const host1 = "https://atomsmdev.hmg.com"; // local DEV url static const host1 = "https://atomsmdev.hmg.com"; // local DEV url
// static const host1 = "https://atomsmuat.hmg.com"; // local UAT 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 getModels => "$_baseUrl/ModelDefinition/GetModelDefinitionAsset"; // get ?client=2
static get getAllRequestsAndCount => "$_baseUrl/CallRequest/GetAllRequestsAndCount"; // get static get getAllRequestsAndCount => "$_baseUrl/CallRequest/GetAllRequestsAndCount"; // get
//service request new flow urls. //service request new flow urls.
static get nurseDashboardCountUrl=> '$_baseUrl/ServiceRequest/GetDashboardNurseCount'; static get nurseDashboardCountUrl => '$_baseUrl/ServiceRequest/GetDashboardNurseCount';
static get nurseDashboardDetailsUrl=> '$_baseUrl/ServiceRequest/GetDashboardNurseDetails';
static get nurseRejectUrl=> '$_baseUrl/ServiceRequest/NurseReject'; static get nurseDashboardDetailsUrl => '$_baseUrl/ServiceRequest/GetDashboardNurseDetails';
static get engineerStopTimer=> '$_baseUrl/ServiceRequest/EngineerStopTimer';
static get nurseConfirmEngineerArrivedUrl=> '$_baseUrl/ServiceRequest/NurseConfirm'; static get nurseRejectUrl => '$_baseUrl/ServiceRequest/NurseReject';
static get nurseConfirmUrl=> '$_baseUrl/ServiceRequest/NurseConfirm';
static get nurseRejectEngineerArrivedUrl=> '$_baseUrl/ServiceRequest/NurseNotArrive'; static get engineerStopTimer => '$_baseUrl/ServiceRequest/EngineerStopTimer';
static get nurseConfirmEngineerArrivalUrl=> '$_baseUrl/ServiceRequest/NurseAccept';
static get engineerDashboardCountUrl=> '$_baseUrl/ServiceRequest/GetDashboardEngineerCount'; static get nurseConfirmEngineerArrivedUrl => '$_baseUrl/ServiceRequest/NurseConfirm';
static get engineerDashboardDetailsUrl=> '$_baseUrl/ServiceRequest/GetDashboardEngineerDetails';
static get engineerDashboardNotAssignDetails=> '$_baseUrl/ServiceRequest/GetDashboardEngineerNotAssignDetails'; static get nurseConfirmUrl => '$_baseUrl/ServiceRequest/NurseConfirm';
static get engineerDashboardUpcoming=> '$_baseUrl/ServiceRequest/GetDashboardEngineerUpcoming';
static get engineerAcceptUrl=> '$_baseUrl/ServiceRequest/EngineerAccept'; static get nurseRejectEngineerArrivedUrl => '$_baseUrl/ServiceRequest/NurseNotArrive';
static get engineerAssignHimSelfUrl=> '$_baseUrl/ServiceRequest/AssignEngineerToHimself';
static get engineerRejectUrl=> '$_baseUrl/ServiceRequest/EngineerReject'; static get nurseConfirmEngineerArrivalUrl => '$_baseUrl/ServiceRequest/NurseAccept';
static get engineerFixRemotlyUrl=> '$_baseUrl/ServiceRequest/EngineerFixRemotly';
static get engineerNeedVisitUrl=> '$_baseUrl/ServiceRequest/EngineerNeedVisit'; static get engineerDashboardCountUrl => '$_baseUrl/ServiceRequest/GetDashboardEngineerCount';
static get engineerUpdateNeedVisitUrl=> '$_baseUrl/ServiceRequest/EngineerUpdateNeedVisit';
static get engineerMarkAsFixUrl=> '$_baseUrl/ServiceRequest/EngineerMarkAsFix'; static get engineerDashboardDetailsUrl => '$_baseUrl/ServiceRequest/GetDashboardEngineerDetails';
static get reOrderActivity=> '$_baseUrl/ServiceRequest/ReOrderActivity';
static get engineerConfirmArriveUrl=> '$_baseUrl/ServiceRequest/EngineerConfirmArrive'; static get engineerDashboardNotAssignDetails => '$_baseUrl/ServiceRequest/GetDashboardEngineerNotAssignDetails';
static get engineerUpdateWorkOrderUrl=> '$_baseUrl/ServiceRequest/EngineerUpdateWorkOrder';
static get engineerSetReminderUrl=> '$_baseUrl/ServiceRequest/EngineerSetReminder'; static get engineerDashboardUpcoming => '$_baseUrl/ServiceRequest/GetDashboardEngineerUpcoming';
static get getWorkOrderByIdUrl=> '$_baseUrl/ServiceRequest/GetWorkOrderById';
static get getQrCodeUrl=> '$_baseUrl/ServiceRequest/GetQRCode'; static get engineerAcceptUrl => '$_baseUrl/ServiceRequest/EngineerAccept';
static get deleteActivitySparePartUrl=> '$_baseUrl/ServiceRequest/DeleteActivitySparePart';
static get deleteActivityMaintenanceUrl=> '$_baseUrl/ServiceRequest/DeleteActivityMaintenance'; static get engineerAssignHimSelfUrl => '$_baseUrl/ServiceRequest/AssignEngineerToHimself';
static get createActivitySparePartUrl=> '$_baseUrl/ServiceRequest/CreateActivitySparePart';
static get createActivityMaintenanceUrl=> '$_baseUrl/ServiceRequest/CreateActivityMaintenance'; static get engineerRejectUrl => '$_baseUrl/ServiceRequest/EngineerReject';
static get createActivityAssetToBeRetiredUrl=> '$_baseUrl/ServiceRequest/CreateActivityAssetToBeRetired';
static get createWorkOrderUrl=> '$_baseUrl/ServiceRequest/CreateWorkOrder'; static get engineerFixRemotlyUrl => '$_baseUrl/ServiceRequest/EngineerFixRemotly';
static get updateActivitySparePartUrl=> '$_baseUrl/ServiceRequest/UpdateActivitySparePart';
static get updateActivityMaintenanceUrl=> '$_baseUrl/ServiceRequest/UpdateActivityMaintenance'; static get engineerNeedVisitUrl => '$_baseUrl/ServiceRequest/EngineerNeedVisit';
static get assignEngineerToWorkOrderUrl=> '$_baseUrl/ServiceRequest/AssignEngineerToWorkOrder';
static get getArrivalVerificationTypeUrl=> '$_baseUrl/ArrivalVerificationType/GetArrivalVerificationType'; static get engineerUpdateNeedVisitUrl => '$_baseUrl/ServiceRequest/EngineerUpdateNeedVisit';
static get sendOtpUrl=> '$_baseUrl/SmsNotification/SendOTP/';
static get verifyOtpUrl=> '$_baseUrl/SmsNotification/VerifyOTP/'; 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 // 08051
//Swipe module Api.. //Swipe module Api..
static get swipeUrl=> '$_baseUrl/Swipe/Swipe'; static get swipeUrl => '$_baseUrl/Swipe/Swipe';
static get getSwipeLastTransactionUrl=> '$_baseUrl/Swipe/GetLastTransaction';
static get getSwipeTransactionHistoryUrl=> '$_baseUrl/Swipe/GetTransactions'; static get getSwipeLastTransactionUrl => '$_baseUrl/Swipe/GetLastTransaction';
static get getSwipeTransactionHistoryUrl => '$_baseUrl/Swipe/GetTransactions';
//Recurrent plan Api... //Recurrent plan Api...
static get getRecurrentPlanByIdUrl=> '$_baseUrl/PlanRecurrentTasks/GetPlanRecurrentTaskById'; static get getRecurrentPlanByIdUrl => '$_baseUrl/PlanRecurrentTasks/GetPlanRecurrentTaskById';
static get updateRecurrentPlanUrl=> '$_baseUrl/PlanRecurrentTasks/UpdateTaskByEngineer';
static get updateRecurrentPlanUrl => '$_baseUrl/PlanRecurrentTasks/UpdateTaskByEngineer';
//Task request apis ... //Task request apis ...
static get getTaskTypeByUserUrl=> '$_baseUrl/TaskTypes/GetTaskTypesByUser'; 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 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 getServiceReportReasons => "$_baseUrl/Lookups/GetLookupReason?lookupEnum=505";
static get getServiceReportRejectionReasons => "$_baseUrl/Lookups/GetLookup?lookupEnum=1303"; static get getServiceReportRejectionReasons => "$_baseUrl/Lookups/GetLookup?lookupEnum=1303";
static get getServiceReportReasonsNew => "$_baseUrl/Lookups/GetLookupReasonNew?lookupEnum=505"; static get getServiceReportReasonsNew => "$_baseUrl/Lookups/GetLookupReasonNew?lookupEnum=505";
static get getServiceReportRetirementType => "$_baseUrl/Lookups/GetLookup?lookupEnum=415"; static get getServiceReportRetirementType => "$_baseUrl/Lookups/GetLookup?lookupEnum=415";
static get getVisitReminderTimeValue => "$_baseUrl/Lookups/GetLookup?lookupEnum=1211"; static get getVisitReminderTimeValue => "$_baseUrl/Lookups/GetLookup?lookupEnum=1211";
static get getServiceReportActivityStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=1302"; static get getServiceReportActivityStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=1302";
static get getServiceReportTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=501"; // get static get getServiceReportTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=501"; // get
static get getServiceReportTypesForWO => "$_baseUrl/Lookups/GetLookup?lookupEnum=34"; // get static get getServiceReportTypesForWO => "$_baseUrl/Lookups/GetLookup?lookupEnum=34"; // get
static get getServiceReportStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=521"; // 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 getAssetTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=500"; // get
static get getPersonRoles => "$_baseUrl/Lookups/GetLookup?lookupEnum=36"; // get static get getPersonRoles => "$_baseUrl/Lookups/GetLookup?lookupEnum=36"; // get
static get getPartNumber => "$_baseUrl/PartCatalog/GetPartAutoComplete"; // 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 getServiceReportPriority => "$_baseUrl/Lookups/GetLookup?lookupEnum=4"; // get
static get getServiceReportDefectTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=601"; // get static get getServiceReportDefectTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=601"; // get
static get getCallRequestForWorkOrder => "$_baseUrl/CallRequest/GetCallRequestForWorkOrder"; // get static get getCallRequestForWorkOrder => "$_baseUrl/CallRequest/GetCallRequestForWorkOrder"; // get
static get attachmentBaseUrl => "https://atomsmdev.hmg.com/v2/mobile/Files/DownloadFile?fileName="; static get attachmentBaseUrl => "https://atomsmdev.hmg.com/v2/mobile/Files/DownloadFile?fileName=";
//gas refill //gas refill
static get getGasTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=606"; // get static get getGasTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=606"; // get
// todo check edits with backend // todo check edits with backend
static get getGasCylinderSize => "$_baseUrl/Lookups/GetLookup?lookupEnum=608"; // get static get getGasCylinderSize => "$_baseUrl/Lookups/GetLookup?lookupEnum=608"; // get
static get getGasCylinderType => "$_baseUrl/Lookups/GetLookup?lookupEnum=607"; // get static get getGasCylinderType => "$_baseUrl/Lookups/GetLookup?lookupEnum=607"; // get
static get getGasStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=609"; // 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 updateGasRefill => "$_baseUrl/GazRefill/UpdateGazRefill"; // get
static get getGasRefill => "$_baseUrl/GazRefill/GetGazRefills"; // 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 getGazRefillComments => "$_baseUrl/GazRefill/GetHistoryComments"; // get
static get addGazRefillComment => "$_baseUrl/GazRefill/AddHistoryComment"; // add static get addGazRefillComment => "$_baseUrl/GazRefill/AddHistoryComment"; // add
static get updateGasRefillByEngineer => "$_baseUrl/GasRefill/UpdateGasRefillByEngineer"; // update
//device transfer //device transfer
static get requestDeviceTransfer => "$_baseUrl/AssetTransfer/AddAssetTransfer"; // get 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 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 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 // employee
static get getEmployees => "$_baseUrl/Lookups/GetLookup?lookupEnum=33"; // get static get getEmployees => "$_baseUrl/Lookups/GetLookup?lookupEnum=33"; // get
static get getEngineers => "$_baseUrl/Account/GetUserByRoleValue?value=R-6"; // get static get getEngineers => "$_baseUrl/Account/GetUserByRoleValue?value=R-6"; // get

@ -4,7 +4,6 @@ import 'package:flutter/widgets.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.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/all_requests_and_count_model.dart';
import 'package:test_sa/models/enums/user_types.dart'; import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/models/ppm/recurrent_wo.dart'; import 'package:test_sa/models/ppm/recurrent_wo.dart';
@ -62,7 +61,7 @@ class AllRequestsProvider extends ChangeNotifier {
// AllRequestsAndCount? get completedRequests => _completedRequests; // AllRequestsAndCount? get completedRequests => _completedRequests;
AllRequestsAndCount? get requestDetailList => _requestDetailList; AllRequestsAndCount? get requestDetailList => _requestDetailList;
RecurrentWoData? _recurrentWoData=RecurrentWoData(); RecurrentWoData? _recurrentWoData = RecurrentWoData();
RecurrentWoData? get recurrentWoData => _recurrentWoData; RecurrentWoData? get recurrentWoData => _recurrentWoData;
@ -201,6 +200,15 @@ class AllRequestsProvider extends ChangeNotifier {
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
recurrentWoData = RecurrentWoData.fromJson(json.decode(response.body)["data"]); 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(); notifyListeners();
} }
isLoading = false; isLoading = false;

@ -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/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/extensions/context_extension.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.dart';
import 'package:test_sa/models/device/asset_transfer.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 'package:test_sa/models/user.dart';
import '../../../models/hospital.dart'; import '../../../models/hospital.dart';
@ -120,15 +122,27 @@ class AssetTransferProvider extends ChangeNotifier {
} }
} }
Future<PendingAssetServiceRequest?> 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<void> createRequest({ Future<void> createRequest({
required BuildContext context, required BuildContext context,
required AssetTransfer assetDestination, required AssetTransfer model,
required Asset asset,
}) async { }) async {
Response response; Response response;
try { try {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); 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; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
if (items != null) { if (items != null) {
@ -148,29 +162,15 @@ class AssetTransferProvider extends ChangeNotifier {
} }
} }
Future<int> updateRequest(BuildContext context, {required AssetTransfer assetTransfer, required bool isSender}) async { Future<int> updateRequest(BuildContext context, {required AssetTransfer model}) async {
Response response; Response response;
try { try {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
response = await ApiManager.instance.put(URLs.updateDeviceTransfer, body: assetTransfer.toJson()); response = await ApiManager.instance.post(URLs.updateDeviceTransfer, body: model.toEngineerUpdateJson());
//print(response.body);
// print("${newModel.engSignature}.png");
// response = await post(
// Uri.parse("$host${URLs.updateDeviceTransfer}/$requestId"),
// body: body,
// );
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
reset(); reset();
// Fluttertoast.showToast(msg: context.translation.successfulRequestMessage);
Navigator.of(context).pop(); Navigator.of(context).pop();
// oldModel.fromDeviceTransfer(
// DeviceTransfer.fromJson(
// json.decode(utf8.decode(response.bodyBytes))[0]
// )
// );
notifyListeners(); notifyListeners();
} else { } else {
Fluttertoast.showToast(msg: "${context.translation.failedToCompleteRequest} :${json.decode(response.body)['message']}"); 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(':\\');
}
} }

@ -1,5 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:developer'; import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.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/extensions/context_extension.dart';
import 'package:test_sa/models/hospital.dart'; import 'package:test_sa/models/hospital.dart';
import 'package:test_sa/models/new_models/gas_refill_model.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 'package:test_sa/models/user.dart';
import '../../../new_views/common_widgets/app_lazy_loading.dart'; import '../../../new_views/common_widgets/app_lazy_loading.dart';
@ -44,12 +46,15 @@ class GasRefillProvider extends ChangeNotifier {
// failed _loading = false // failed _loading = false
bool isLoading = false; bool isLoading = false;
Future<GasRefillModel?> getGasRefillObjectById(num id) async { Future<GasRefillModel?> getGasRefillObjectById(num id) async {
try { 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) { if (response.statusCode >= 200 && response.statusCode < 300) {
return GasRefillModel.fromJson(json.decode(response.body)["data"]);
return GasRefillModel.fromJson(json.decode(response.body)["data"]);
} else { } else {
return null; return null;
} }
@ -58,6 +63,7 @@ class GasRefillProvider extends ChangeNotifier {
} }
} }
/// return -2 if request in progress /// return -2 if request in progress
/// return -1 if error happen when sending request /// return -1 if error happen when sending request
/// return state code if request complete may be 200, 404 or 403 /// return state code if request complete may be 200, 404 or 403
@ -105,20 +111,14 @@ class GasRefillProvider extends ChangeNotifier {
} }
} }
Future<void> createModel({ Future<void> addGasRefillRequest({
required BuildContext context, required BuildContext context,
required User user,
required GasRefillModel model, required GasRefillModel model,
}) async { }) async {
late Response response; late Response response;
try { try {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
final Map<String, dynamic> body = { response = await ApiManager.instance.post(URLs.requestGasRefill, body: model.toJson());
"uid": user.id.toString(),
"token": user.token ?? "",
};
body.addAll(model.toJson());
response = await ApiManager.instance.post(URLs.requestGasRefill, body: body);
stateCode = response.statusCode; stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
if (items != null) { if (items != null) {
@ -137,6 +137,23 @@ class GasRefillProvider extends ChangeNotifier {
} }
} }
Future<int> 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<int> updateModel({ Future<int> updateModel({
required String host, required String host,
required User user, required User user,
@ -145,7 +162,7 @@ class GasRefillProvider extends ChangeNotifier {
}) async { }) async {
Map<String, dynamic> body = { Map<String, dynamic> body = {
"id": newModel.id, "id": newModel.id,
"gazRefillNo": newModel.gazRefillNo ?? "", "gasRefillNo": newModel.gasRefillNo ?? "",
"status": newModel.status?.toJson(), "status": newModel.status?.toJson(),
//"expectedDate": newModel.expectedDate?.toIso8601String(), //"expectedDate": newModel.expectedDate?.toIso8601String(),
"expectedTime": newModel.expectedDate, "expectedTime": newModel.expectedDate,
@ -164,7 +181,7 @@ class GasRefillProvider extends ChangeNotifier {
"comment": newModel.comment, "comment": newModel.comment,
}; };
body["gazRefillDetails"] = newModel.gazRefillDetails! body["gasRefillDetails"] = newModel.gasRefillDetails!
.map((model) => { .map((model) => {
"gasType": model.gasType?.toJson(), "gasType": model.gasType?.toJson(),
"cylinderSize": model.cylinderSize?.toJson(), "cylinderSize": model.cylinderSize?.toJson(),

@ -96,11 +96,29 @@ class PartsProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received // client's request was successfully received
List categoriesListJson = json.decode(response.body)["data"]; 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; return page;
} catch (error) { } catch (error) {
return []; return [];
} }
} }
// Implement this only for spare part request for now show and search on display name ....
Future<List<SparePart>> getPartsListByDisplayName({num? assetId, String? displayName}) async {
late Response response;
try {
response = await ApiManager.instance.post(URLs.getPartNumber, body: {"displayName": displayName, });
List<SparePart> 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 [];
}
}
} }

@ -22,6 +22,14 @@ class PpmProvider extends ChangeNotifier {
PlanPreventiveVisit? _planPreventiveVisit; PlanPreventiveVisit? _planPreventiveVisit;
late int _totalTabs = 4; late int _totalTabs = 4;
TabController? tabController; TabController? tabController;
bool _isReadOnly = false;
bool get isReadOnly => _isReadOnly;
set isReadOnly(bool value) {
_isReadOnly = value;
notifyListeners();
}
int get totalTabs => _totalTabs; int get totalTabs => _totalTabs;
@ -155,6 +163,11 @@ class PpmProvider extends ChangeNotifier {
if (response.statusCode >= 200 && response.statusCode < 300) { if (response.statusCode >= 200 && response.statusCode < 300) {
ppmPlanAttachments = []; ppmPlanAttachments = [];
planPreventiveVisit = PlanPreventiveVisit.fromJson(json.decode(response.body)["data"]); planPreventiveVisit = PlanPreventiveVisit.fromJson(json.decode(response.body)["data"]);
if(planPreventiveVisit?.visitStatus?.value! == 1 || planPreventiveVisit?.visitStatus?.value == 3){
isReadOnly =true;
}else{
isReadOnly =false;
}
isLoading = false; isLoading = false;
notifyListeners(); notifyListeners();
return planPreventiveVisit; return planPreventiveVisit;

@ -367,16 +367,16 @@ class CategoryTabs {
if (userType == UsersTypes.engineer) { if (userType == UsersTypes.engineer) {
// tabs.add(CategoryTabs(label: 'Upcoming', tag: 0, id: 0)); // tabs.add(CategoryTabs(label: 'Upcoming', tag: 0, id: 0));
// tabs.add(CategoryTabs('Open', 1)); // tabs.add(CategoryTabs('Open', 1));
tabs.add(CategoryTabs(label: 'UnAssigned Open', tag: 1, id: 1)); tabs.add(CategoryTabs(label: 'UnAssigned', tag: 1, id: 1));
tabs.add(CategoryTabs(label: 'Assigned Open', 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: 'In Progress', tag: 2, id: 3));
tabs.add(CategoryTabs(label: 'Completed', tag: 3, id: 4)); tabs.add(CategoryTabs(label: 'Completed', tag: 3, id: 4));
return tabs; 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: '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)); tabs.add(CategoryTabs(label: 'Canceled', tag: 6, id: 4));
return tabs; return tabs;
} }

@ -151,10 +151,9 @@
// //
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:pie_chart/pie_chart.dart';
import 'package:provider/provider.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/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/context_extension.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
@ -212,46 +211,44 @@ class ProgressFragment extends StatelessWidget {
child: Stack( child: Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
SfCircularChart( PieChart(
tooltipBehavior: TooltipBehavior( dataMap: {for (var v in chartData) v.x: v.y},
enable: true, animationDuration: const Duration(milliseconds: 800),
// elevation: 2, chartLegendSpacing: 32,
color: context.isDark ? const Color(0xFF111427) : const Color(0xffF7F9FB), chartRadius: MediaQuery.of(context).size.width / 3.2,
textStyle: context.isDark ? null : const TextStyle(color: Colors.black87, fontSize: 12), 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, chartValuesOptions: const ChartValuesOptions(
), showChartValueBackground: false,
series: <CircularSeries>[ showChartValues: false,
DoughnutSeries<ChartData, String>( showChartValuesInPercentage: false,
dataSource: chartData, showChartValuesOutside: false,
radius: "100%", decimalPlaces: 1,
innerRadius: "60%", ),
pointColorMapper: (ChartData data, _) => data.color, ).toShimmer(isShow: snapshot.isAllCountLoading, radius: 250).paddingAll(0).toShadowContainer(context),
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),
),
],
),
], ],
), ),
), ),

@ -164,13 +164,14 @@ extension CapExtension on String {
String get allInCaps => toUpperCase(); String get allInCaps => toUpperCase();
String get cleanupWhitespace => replaceAll(RegExp(r"\s+"), " "); String get cleanupWhitespace => this;//replaceAll(RegExp(r"\s+"), " ");
String get capitalizeFirstOfEach => trim().isNotEmpty String get capitalizeFirstOfEach => this;
? trim().toLowerCase().split(" ").map((str) { //trim().isNotEmpty
return str.trim()?.inCaps ?? ""; // ? trim().toLowerCase().split(" ").map((str) {
}).join(" ") // return str.trim()?.inCaps ?? "";
: ""; // }).join(" ")
// : "";
} }
extension FilesExtension on String { extension FilesExtension on String {

@ -4,6 +4,7 @@ import 'package:shimmer/shimmer.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_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'; 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 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 Widget toShimmer({bool isShow = true, double radius = 20}) => isShow
? Shimmer.fromColors( ? Shimmer.fromColors(
baseColor: const Color(0xffe8eff0), baseColor: const Color(0xffe8eff0),

@ -560,6 +560,16 @@
"installationBuilding": "مبنى التركيب", "installationBuilding": "مبنى التركيب",
"installationFloor": "طابق التركيب", "installationFloor": "طابق التركيب",
"installationDepartment": "قسم التركيب", "installationDepartment": "قسم التركيب",
"acknowledge": "إقرار" "acknowledge": "إقرار",
"transferAsset": "نقل الأصل",
"createAssetTransferRequest": "إنشاء طلب نقل أصل",
"arrivedDate": "تاريخ الوصول",
"closedDate": "تاريخ الإغلاق",
"since": "منذ",
"rejectionDetails": "تفاصيل الرفض",
"part": "جزء",
"closedDate": "تاريخ الإغلاق",
"creationDate": "تاريخ الإنشاء"
} }

@ -563,5 +563,15 @@
"installationBuilding": "Installation Building", "installationBuilding": "Installation Building",
"installationFloor": "Installation Floor", "installationFloor": "Installation Floor",
"installationDepartment": "Installation Department", "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"
} }

@ -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/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_filter_screen.dart';
import 'package:test_sa/views/pages/device_transfer/asset_search_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/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/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/request_gas_refill.dart';
import 'package:test_sa/views/pages/user/gas_refill/track_gas_refill.dart'; import 'package:test_sa/views/pages/user/gas_refill/track_gas_refill.dart';
import 'package:test_sa/views/pages/user/notifications/notifications_page.dart'; import 'package:test_sa/views/pages/user/notifications/notifications_page.dart';
@ -308,6 +309,7 @@ class MyApp extends StatelessWidget {
CreateTaskView.id: (_) => const CreateTaskView(), CreateTaskView.id: (_) => const CreateTaskView(),
//ReportIssuesPage.id: (_) => ReportIssuesPage(), //ReportIssuesPage.id: (_) => ReportIssuesPage(),
RequestGasRefill.id: (_) => const RequestGasRefill(), RequestGasRefill.id: (_) => const RequestGasRefill(),
GasRefillForm.id: (_) => const GasRefillForm(),
CreateServiceRequestPage.id: (_) => const CreateServiceRequestPage(), CreateServiceRequestPage.id: (_) => const CreateServiceRequestPage(),
CreateNewRequest.id: (_) => const CreateNewRequest(), CreateNewRequest.id: (_) => const CreateNewRequest(),
// SingleHospitalPicker.id: (_) => SingleHospitalPicker(), // SingleHospitalPicker.id: (_) => SingleHospitalPicker(),
@ -318,7 +320,7 @@ class MyApp extends StatelessWidget {
// PreventiveMaintenanceVisitsPage.id: (_) => PreventiveMaintenanceVisitsPage(), // PreventiveMaintenanceVisitsPage.id: (_) => PreventiveMaintenanceVisitsPage(),
PpmPage.id: (_) => const PpmPage(), PpmPage.id: (_) => const PpmPage(),
TrackGasRefillPage.id: (_) => const TrackGasRefillPage(), TrackGasRefillPage.id: (_) => const TrackGasRefillPage(),
RequestDeviceTransfer.id: (_) => const RequestDeviceTransfer(), CreateAssetTransferRequest.id: (_) => const CreateAssetTransferRequest(),
TrackDeviceTransferPage.id: (_) => const TrackDeviceTransferPage(), TrackDeviceTransferPage.id: (_) => const TrackDeviceTransferPage(),
// todo remove this class after work // todo remove this class after work

@ -2,86 +2,100 @@ import 'package:flutter/src/widgets/framework.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/device/asset.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/ppm/ppm.dart';
import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/models/timer_model.dart';
import 'asset_transfer_attachment.dart'; import 'asset_transfer_attachment.dart';
class AssetTransfer { class AssetTransfer {
AssetTransfer( AssetTransfer({
{this.id, this.id,
this.transferNo, this.transferNo,
this.transferCode, this.transferType,
this.assetId, this.transferCode,
this.destSiteId, this.assetId,
this.destBuildingId, this.destSiteId,
this.destFloorId, this.destBuildingId,
this.destDepartmentId, this.destFloorId,
this.destRoomId, this.destDepartmentId,
this.senderSiteId, this.destRoomId,
this.senderBuildingId, this.senderSiteId,
this.senderFloorId, this.senderBuildingId,
this.senderDepartmentId, this.senderFloorId,
this.senderRoom, this.senderDepartmentId,
this.senderAssignedEmployeeId, this.senderRoom,
this.senderMachineStatusId, this.senderAssignedEmployeeId,
this.senderComment, this.senderMachineStatusId,
this.comment, this.senderComment,
this.receiverEndUserId, this.comment,
this.receiverEndUserName, this.receiverEndUserId,
this.senderStartDate, this.receiverEndUserName,
this.senderEndDate, this.senderStartDate,
this.senderWorkingHours, this.senderEndDate,
this.senderTravelingHours, this.senderWorkingHours,
this.senderEngSignature, this.senderTravelingHours,
this.senderAttachments, this.senderEngSignature,
this.receiverAssignedEmployeeId, this.senderAttachments,
this.receiverMachineStatusId, this.receiverAssignedEmployeeId,
this.receiverComment, this.receiverMachineStatusId,
this.receiverStartDate, this.receiverComment,
this.receiverEndDate, this.receiverStartDate,
this.receiverWorkingHours, this.receiverEndDate,
this.receiverTravelingHours, this.receiverWorkingHours,
this.receiverEngSignature, this.receiverTravelingHours,
this.receiverAttachments, this.receiverEngSignature,
this.assetNumber, this.receiverAttachments,
this.assetName, this.attachments,
this.manufacturerName, this.assetNumber,
this.modelName, this.assetName,
this.assetSerialNo, this.manufacturerName,
this.destDepartmentName, this.modelName,
this.destBuildingName, this.assetSerialNo,
this.applied, this.destDepartmentName,
this.extensionNo, this.destBuildingName,
this.name, this.applied,
this.employeeId, this.isSender,
this.createdDate, this.extensionNo,
this.createdOn, this.name,
this.destFloorName, this.employeeId,
this.destSiteName, this.createdDate,
this.manufacturerId, this.createdOn,
this.modelId, this.destFloorName,
this.modifiedOn, this.destSiteName,
this.receiverAssignedEmployeeName, this.manufacturerId,
this.receiverEngSignatureUrl, this.modelId,
this.receiverMachineStatusName, this.modifiedOn,
this.senderAssignedEmployeeName, this.receiverAssignedEmployeeName,
this.senderBuildingName, this.receiverEngSignatureUrl,
this.senderDepartmentName, this.receiverMachineStatusName,
this.senderEngSignatureUrl, this.senderAssignedEmployeeName,
this.senderFloorName, this.senderBuildingName,
this.senderMachineStatusName, this.senderDepartmentName,
this.senderSiteName, this.senderEngSignatureUrl,
this.supplierId, this.senderFloorName,
this.supplierName, this.senderMachineStatusName,
this.senderVisitTimers, this.senderSiteName,
this.receiverVisitTimers, this.supplierId,
this.tbsTimer}); 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) { AssetTransfer.fromJson(dynamic json) {
id = json['id']; id = json['id'];
transferNo = json['transferNo']; transferNo = json['transferNo'];
transferCode = json['transferCode']; transferCode = json['transferCode'];
transferType = json["transferType"] == null ? null : Lookup.fromJson(json["transferType"]);
assetId = json['assetId']; assetId = json['assetId'];
destSiteId = json['destSiteId']; destSiteId = json['destSiteId'];
destBuildingId = json['destBuildingId']; destBuildingId = json['destBuildingId'];
@ -130,6 +144,19 @@ class AssetTransfer {
receiverVisitTimers!.add(VisitTimers.fromJson(v)); 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(); tbsTimer = TimerModel();
// try { // try {
// receiverTimer = TimerModel(startAt: DateTime.tryParse(receiverStartDate ?? ""), endAt: DateTime.tryParse(receiverEndDate ?? "")); // receiverTimer = TimerModel(startAt: DateTime.tryParse(receiverStartDate ?? ""), endAt: DateTime.tryParse(receiverEndDate ?? ""));
@ -151,6 +178,13 @@ class AssetTransfer {
receiverAttachments!.add(AssetTransferAttachment.fromJson(v)); 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']; assetNumber = json['assetNumber'];
assetName = json['assetName']; assetName = json['assetName'];
manufacturerName = json['manufacturerName']; manufacturerName = json['manufacturerName'];
@ -186,6 +220,8 @@ class AssetTransfer {
num? id; num? id;
num? transferNo; num? transferNo;
String? transferCode; String? transferCode;
int? statusValue;
Lookup? transferType;
String? assetSerialNo; String? assetSerialNo;
num? assetId; num? assetId;
String? assetNumber; String? assetNumber;
@ -216,6 +252,7 @@ class AssetTransfer {
String? senderTravelingHours; String? senderTravelingHours;
String? senderEngSignature; String? senderEngSignature;
List<AssetTransferAttachment>? senderAttachments; List<AssetTransferAttachment>? senderAttachments;
List<AssetTransferAttachment>? attachments;
String? receiverAssignedEmployeeId; String? receiverAssignedEmployeeId;
num? receiverMachineStatusId; num? receiverMachineStatusId;
String? receiverComment; String? receiverComment;
@ -242,6 +279,7 @@ class AssetTransfer {
String? receiverMachineStatusName; String? receiverMachineStatusName;
String? receiverEngSignatureUrl; String? receiverEngSignatureUrl;
bool? applied; bool? applied;
bool? isSender;
dynamic extensionNo; dynamic extensionNo;
String? employeeId; String? employeeId;
String? name; String? name;
@ -250,12 +288,21 @@ class AssetTransfer {
String? modifiedOn; String? modifiedOn;
List<VisitTimers>? senderVisitTimers; List<VisitTimers>? senderVisitTimers;
List<VisitTimers>? receiverVisitTimers; List<VisitTimers>? receiverVisitTimers;
List<VisitTimers>? assetTransferEngineerTimers;
List<TimerModel>? timerModelList = [];
List<AssistantEmployees>? assistantEmployees;
List<AssetTransferAssistantEmployees>? assetTransferAssistantEmployeesSender;
List<AssetTransferAssistantEmployees>? assetTransferAssistantEmployeesReceiver;
AssetTransferAssistantEmployees? modelAssistantEmployees;
TimerModel? tbsTimer = TimerModel(); TimerModel? tbsTimer = TimerModel();
AssetTransfer copyWith( AssetTransfer copyWith(
{num? id, {num? id,
num? transferNo, num? transferNo,
String? transferCode, String? transferCode,
Lookup? transferType,
num? assetId, num? assetId,
num? destSiteId, num? destSiteId,
num? destBuildingId, num? destBuildingId,
@ -326,6 +373,7 @@ class AssetTransfer {
id: id ?? this.id, id: id ?? this.id,
transferNo: transferNo ?? this.transferNo, transferNo: transferNo ?? this.transferNo,
transferCode: transferCode ?? this.transferCode, transferCode: transferCode ?? this.transferCode,
transferType: transferType ?? this.transferType,
assetId: assetId ?? this.assetId, assetId: assetId ?? this.assetId,
destSiteId: destSiteId ?? this.destSiteId, destSiteId: destSiteId ?? this.destSiteId,
destBuildingId: destBuildingId ?? this.destBuildingId, destBuildingId: destBuildingId ?? this.destBuildingId,
@ -375,10 +423,10 @@ class AssetTransfer {
receiverMachineStatusName: receiverMachineStatusName ?? this.receiverMachineStatusName, receiverMachineStatusName: receiverMachineStatusName ?? this.receiverMachineStatusName,
receiverEngSignatureUrl: receiverEngSignatureUrl ?? this.receiverEngSignatureUrl, receiverEngSignatureUrl: receiverEngSignatureUrl ?? this.receiverEngSignatureUrl,
applied: applied ?? this.applied, applied: applied ?? this.applied,
extensionNo: extensionNo??this.extensionNo, extensionNo: extensionNo ?? this.extensionNo,
employeeId: employeeId??this.employeeId, employeeId: employeeId ?? this.employeeId,
name: name??this.name, name: name ?? this.name,
createdDate: createdDate??this.createdDate, createdDate: createdDate ?? this.createdDate,
createdOn: createdOn ?? this.createdOn, createdOn: createdOn ?? this.createdOn,
modifiedOn: modifiedOn ?? this.modifiedOn, modifiedOn: modifiedOn ?? this.modifiedOn,
assetSerialNo: assetSerialNo ?? this.assetSerialNo, assetSerialNo: assetSerialNo ?? this.assetSerialNo,
@ -472,6 +520,48 @@ class AssetTransfer {
return map; return map;
} }
Map<String, dynamic> toCreateAssetTransferJson() {
final map = <String, dynamic>{};
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<String, dynamic> toEngineerUpdateJson() {
final map = <String, dynamic>{};
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<String, dynamic> transferBody({Asset? asset}) { Map<String, dynamic> transferBody({Asset? asset}) {
final map = <String, dynamic>{}; final map = <String, dynamic>{};
map['id'] = 0; map['id'] = 0;
@ -526,6 +616,7 @@ class AssetTransfer {
if (assetTransfer == null) return; if (assetTransfer == null) return;
id = assetTransfer.id; id = assetTransfer.id;
transferNo = assetTransfer.transferNo; transferNo = assetTransfer.transferNo;
transferType = assetTransfer.transferType;
transferCode = assetTransfer.transferCode; transferCode = assetTransfer.transferCode;
assetId = assetTransfer.assetId; assetId = assetTransfer.assetId;
destSiteId = assetTransfer.destSiteId; destSiteId = assetTransfer.destSiteId;
@ -591,6 +682,8 @@ class AssetTransfer {
manufacturerName = assetTransfer.manufacturerName; manufacturerName = assetTransfer.manufacturerName;
senderVisitTimers = assetTransfer.senderVisitTimers; senderVisitTimers = assetTransfer.senderVisitTimers;
receiverVisitTimers = assetTransfer.receiverVisitTimers; receiverVisitTimers = assetTransfer.receiverVisitTimers;
assetTransferAssistantEmployeesReceiver = assetTransfer.assetTransferAssistantEmployeesReceiver;
assetTransferAssistantEmployeesSender = assetTransfer.assetTransferAssistantEmployeesSender;
} }
Future<bool> validate(BuildContext context) async { Future<bool> validate(BuildContext context) async {
@ -613,3 +706,42 @@ class AssetTransfer {
return true; 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<String, dynamic> 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<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['startDate'] = startDate?.toIso8601String();
data['endDate'] = endDate?.toIso8601String();
data['workingHours'] = workingHours;
data['techComment'] = techComment;
data['employeeId'] = employeeId;
return data;
}
}

@ -12,7 +12,6 @@ class ActivityMaintenanceHelperModel {
//remove this //remove this
int? lastSituationId; int? lastSituationId;
Lookup? lastSituation; Lookup? lastSituation;
Lookup? activityStatus; Lookup? activityStatus;
DateTime? startTime; DateTime? startTime;
DateTime? endTime; DateTime? endTime;

@ -41,6 +41,14 @@ class WorkOrderHelperModel {
} }
return data; return data;
} }
Map<String, dynamic> toUploadAttachmentJson(int? workOrderId,List<WorkOrderAttachments>? workOrderAttachments) {
final Map<String, dynamic> data = <String, dynamic>{};
data['workOrderId'] = workOrderId;
if (workOrderAttachments != null) {
data['workOrderAttachments'] = workOrderAttachments!.map((v) => v.toJson()).toList();
}
return data;
}
} }
class WorkOrderAttachments { class WorkOrderAttachments {
@ -73,6 +81,7 @@ class EngineerUpdateWorkOrderHelperModel {
Lookup? failureReason; Lookup? failureReason;
FaultDescription? faultDescription; FaultDescription? faultDescription;
String? solution; String? solution;
String? callResponse;
EngineerUpdateWorkOrderHelperModel({ EngineerUpdateWorkOrderHelperModel({
this.workOrderId, this.workOrderId,
@ -85,6 +94,7 @@ class EngineerUpdateWorkOrderHelperModel {
this.serviceType, this.serviceType,
this.solution, this.solution,
this.returnToService, this.returnToService,
this.callResponse,
}); });
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
@ -96,6 +106,7 @@ class EngineerUpdateWorkOrderHelperModel {
data['loanAssetId'] = loanAssetId; data['loanAssetId'] = loanAssetId;
data['failureReasonId'] = failureReason?.id; data['failureReasonId'] = failureReason?.id;
data['faultDescriptionId'] = faultDescription?.id; data['faultDescriptionId'] = faultDescription?.id;
data['callResponse'] = callResponse;
return data; return data;
} }
} }

@ -1,5 +1,6 @@
import 'package:test_sa/models/base.dart'; import 'package:test_sa/models/base.dart';
import 'package:test_sa/models/new_models/assigned_employee.dart'; import 'package:test_sa/models/new_models/assigned_employee.dart';
// int? id; // int? id;
// String? userId; // String? userId;
// DateTime? startDate; // DateTime? startDate;
@ -7,9 +8,9 @@ import 'package:test_sa/models/new_models/assigned_employee.dart';
// int? workingHours; // int? workingHours;
// String? technicalComment; // String? technicalComment;
class AssistantEmployees extends Base { class AssistantEmployees extends Base {
String? userId; String? userId;
AssistantEmployees({ AssistantEmployees({
this.id, this.id,
this.user, this.user,

@ -12,37 +12,77 @@ import 'package:test_sa/models/new_models/site.dart';
import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/models/timer_model.dart';
class GasRefillModel { class GasRefillModel {
GasRefillModel( GasRefillModel({
{this.id, this.id,
this.gazRefillNo, this.gasRefillNo,
this.expectedDate, this.expectedDate,
this.expectedTime, this.expectedTime,
this.startDate, this.startDate,
this.startTime, this.startTime,
this.endDate, this.endDate,
this.endTime, this.endTime,
this.engSignature, this.engSignature,
this.nurseSignature, this.nurseSignature,
this.workingHours, this.workingHours,
this.extensionNo, this.extensionNo,
this.employeeId, this.employeeId,
this.name, this.name,
this.createdDate, this.createdDate,
this.site, this.site,
this.building, this.building,
this.floor, this.floor,
this.department, this.department,
this.assignedEmployee, this.assignedEmployee,
this.status, this.status,
this.comment, this.comment,
this.gazRefillDetails, this.techComment,
this.localEngineerSignature, this.gasRefillDetails,
this.localNurseSignature, this.localEngineerSignature,
this.timer}); 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>? gasRefillDetails; // Now nullable
Uint8List? localNurseSignature; // Now nullable
Uint8List? localEngineerSignature; // Now nullable
TimerModel? timer = TimerModel();
//TODO need to check when api provided..
List<TimerModel>? timerModelList = [];
List<GasRefillTimer>? gasRefillTimers = [];
List<GasRefillAttachments>? gasRefillAttachments;
int? statusValue;
GasRefillModel.fromJson(dynamic json) { GasRefillModel.fromJson(dynamic json) {
id = json['id']; id = json['id'];
gazRefillNo = json['gazRefillNo']; gasRefillNo = json['gasRefillNo'];
expectedDate = json['expectedDate']; expectedDate = json['expectedDate'];
expectedTime = json['expectedTime']; expectedTime = json['expectedTime'];
startDate = json['startDate']; startDate = json['startDate'];
@ -50,28 +90,44 @@ class GasRefillModel {
endDate = json['endDate']; endDate = json['endDate'];
endTime = json['endTime']; endTime = json['endTime'];
comment = json['comment']; comment = json['comment'];
techComment = json['techComment'];
workingHours = json['workingHours']; workingHours = json['workingHours'];
extensionNo = json['extensionNo']; extensionNo = json['extensionNo'];
employeeId = json['employeeId']; employeeId = json['employeeId'];
name = json['name']; name = json['name'];
createdDate = json['createdDate']; createdDate = json['createdDate'];
try { if (json['gasRefillTimers'] != null) {
final DateTime? sd = DateTime.tryParse(startDate ?? ""); gasRefillTimers = <GasRefillTimer>[];
final DateTime? st = DateTime.tryParse(startTime ?? ""); json['gasRefillTimers'].forEach((v) {
final DateTime? ed = DateTime.tryParse(endDate ?? ""); gasRefillTimers?.add(GasRefillTimer.fromJson(v));
final DateTime? et = DateTime.tryParse(endTime ?? ""); });
timer = TimerModel( workingHours = json['gasRefillTimers'].fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item['endDate']).difference(DateTime.parse(item['startDate'])).inSeconds) ?? 0;
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 (json['gasRefillAttachments'] != null) {
if (timer!.endAt != null && timer!.startAt != null) { gasRefillAttachments = <GasRefillAttachments>[];
// Use '!' since timer could be null after initialization json['gasRefillAttachments'].forEach((v) {
timer!.durationInSecond = (timer!.endAt!.difference(timer!.startAt!)).inSeconds; gasRefillAttachments!.add(GasRefillAttachments.fromJson(v));
workingHours = (((timer!.durationInSecond ?? 0) / 60) / 60); });
}
} catch (e) {
print(e);
} }
// 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']; engSignature = json['engSignature'];
nurseSignature = json['nurseSignature']; nurseSignature = json['nurseSignature'];
site = json['site'] != null ? Site.fromJson(json['site']) : null; site = json['site'] != null ? Site.fromJson(json['site']) : null;
@ -80,129 +136,93 @@ class GasRefillModel {
department = json['department'] != null ? Department.fromJson(json['department']) : null; department = json['department'] != null ? Department.fromJson(json['department']) : null;
assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null; assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null;
status = json['status'] != null ? Lookup.fromJson(json['status']) : null; status = json['status'] != null ? Lookup.fromJson(json['status']) : null;
if (json['gazRefillDetails'] != null) { if (json['gasRefillDetails'] != null) {
gazRefillDetails = []; gasRefillDetails = [];
json['gazRefillDetails'].forEach((v) { json['gasRefillDetails'].forEach((v) {
gazRefillDetails!.add(GasRefillDetails.fromJson(v)); // Use '!' since gazRefillDetails is initialized here 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<GasRefillDetails>? 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<GasRefillDetails>? 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<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final map = <String, dynamic>{}; final map = <String, dynamic>{};
map['id'] = id ?? 0; map['id'] = id ?? 0;
map['gazRefillNo'] = "GR-${DateTime.now().toString().split(" ").first}"; map['gasTypeId'] = gasRefillDetails?[0].gasType?.id;
map['expectedDate'] = expectedDate; map['cylinderTypeId'] = gasRefillDetails?[0].cylinderType?.id;
map['expectedTime'] = expectedTime; map['cylinderSizeId'] = gasRefillDetails?[0].cylinderSize?.id;
map['startDate'] = startDate; map['requestedQty'] = gasRefillDetails?[0].requestedQty;
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) { if (site != null) {
map['site'] = site?.toJson(addBuildings: false); // Use '?.' for null safety map['siteId'] = site?.id; // Use '?.' for null safety
} }
if (building != null) { if (building != null) {
map['building'] = building?.toJson(addFloor: false); // Use '?.' for null safety map['buildingId'] = building?.id; // Use '?.' for null safety
} }
if (floor != null) { if (floor != null) {
map['floor'] = floor?.toJson(addDepartments: false); // Use '?.' for null safety map['floorId'] = floor?.id; // Use '?.' for null safety
} }
if (department != null) { if (department != null) {
map['department'] = department?.toJson(); // Use '?.' for null safety map['departmentId'] = department?.id; // Use '?.' for null safety
} }
if (assignedEmployee != null) { map['comment'] = comment;
map['assignedEmployee'] = assignedEmployee?.toJson(); // Use '?.' for null safety
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<String, dynamic> toUpdateEngineerPayload({required int status}) {
final map = <String, dynamic>{};
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) { if (gasRefillAttachments != null) {
map['gazRefillDetails'] = gazRefillDetails!.map((v) => v.toJson()).toList(); // Use '!' since gazRefillDetails could be null map['gasRefillAttachments'] = gasRefillAttachments?.map((v) => v.toJson()).toList();
} }
return map; return map;
} }
@ -227,9 +247,9 @@ class GasRefillModel {
id = model.id; id = model.id;
//userId = model.userId; //userId = model.userId;
site = model.site; site = model.site;
gazRefillNo = model.gazRefillNo; gasRefillNo = model.gasRefillNo;
status = Lookup.fromStatus(model.status); status = Lookup.fromStatus(model.status);
gazRefillDetails = model.gazRefillDetails; gasRefillDetails = model.gasRefillDetails;
building = model.building; building = model.building;
floor = model.floor; floor = model.floor;
department = model.department; department = model.department;
@ -246,8 +266,63 @@ class GasRefillModel {
extensionNo = model.extensionNo; extensionNo = model.extensionNo;
employeeId = model.employeeId; employeeId = model.employeeId;
name = model.name; name = model.name;
techComment = model.techComment;
gasRefillAttachments = model.gasRefillAttachments;
createdDate = model.createdDate; 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>? gasRefillDetails,
List<GasRefillTimer>? 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 { class GasRefillDetails {
@ -331,3 +406,50 @@ class GasRefillDetails {
return true; return true;
} }
} }
class GasRefillTimer {
int? id;
String? startDate;
String? endDate;
dynamic workingHours;
GasRefillTimer({this.id, this.startDate, this.endDate, this.workingHours});
GasRefillTimer.fromJson(Map<String, dynamic> json) {
id = json['id'];
startDate = json['startDate'];
endDate = json['endDate'];
workingHours = json['workingHours'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
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<String, dynamic> json) {
id = json['id'];
gasRefillId = json['gasRefillId'];
attachmentName = json['attachmentName'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['gasRefillId'] = gasRefillId;
data['attachmentName'] = attachmentName;
return data;
}
}

@ -84,6 +84,13 @@ class WorkOrderData {
required this.totalWorkingHours, required this.totalWorkingHours,
this.needAVisitComment, this.needAVisitComment,
this.needAVisitDateTime, this.needAVisitDateTime,
this.iHaveArrivedDate,
this.rejectReason,
this.closedDate,
this.since,
this.cmFrame,
this.rejectComment,
this.callResponse,
required this.workOrderHistory, required this.workOrderHistory,
required this.activities, required this.activities,
required this.activityAssetToBeRetireds, required this.activityAssetToBeRetireds,
@ -127,9 +134,18 @@ class WorkOrderData {
Lookup? failureReasone; Lookup? failureReasone;
FaultDescription? faultDescription; FaultDescription? faultDescription;
Lookup? solution; Lookup? solution;
Lookup? cmFrame;
//cmComments
String? totalWorkingHours; String? totalWorkingHours;
DateTime? needAVisitDateTime; DateTime? needAVisitDateTime;
String? needAVisitComment; 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> workOrderHistory; List<WorkOrderHistory> workOrderHistory;
List<Activities> activities; List<Activities> activities;
List<dynamic> activityAssetToBeRetireds; List<dynamic> activityAssetToBeRetireds;
@ -150,6 +166,13 @@ class WorkOrderData {
floor: json["floor"] == null ? null : Lookup.fromJson(json["floor"]), floor: json["floor"] == null ? null : Lookup.fromJson(json["floor"]),
department: json["department"] == null ? null : AssetGroup.fromJson(json["department"]), department: json["department"] == null ? null : AssetGroup.fromJson(json["department"]),
room: json["room"], 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"]), assetType: json["assetType"] == null ? null : Lookup.fromJson(json["assetType"]),
assignedEmployee: json["assignedEmployee"] == null ? null : WorkOrderAssignedEmployee.fromJson(json["assignedEmployee"]), assignedEmployee: json["assignedEmployee"] == null ? null : WorkOrderAssignedEmployee.fromJson(json["assignedEmployee"]),
lastActivityStatus: json["lastActivityStatus"] != null ? Lookup.fromJson(json["lastActivityStatus"]) : null, lastActivityStatus: json["lastActivityStatus"] != null ? Lookup.fromJson(json["lastActivityStatus"]) : null,
@ -174,7 +197,7 @@ class WorkOrderData {
failureReasone: json["failureReasone"] == null ? null : Lookup.fromJson(json["failureReasone"]), failureReasone: json["failureReasone"] == null ? null : Lookup.fromJson(json["failureReasone"]),
faultDescription: json["faultDescription"] == null ? null : FaultDescription.fromJson(json["faultDescription"]), faultDescription: json["faultDescription"] == null ? null : FaultDescription.fromJson(json["faultDescription"]),
solution: json["solution"] == null ? null : Lookup.fromJson(json["solution"]), solution: json["solution"] == null ? null : Lookup.fromJson(json["solution"]),
totalWorkingHours: (json["totalWorkingHours"] ??"").toString(), totalWorkingHours: (json["totalWorkingHours"] ?? "").toString(),
workOrderHistory: json["workOrderHistory"] == null ? [] : List<WorkOrderHistory>.from(json["workOrderHistory"]!.map((x) => WorkOrderHistory.fromJson(x))), workOrderHistory: json["workOrderHistory"] == null ? [] : List<WorkOrderHistory>.from(json["workOrderHistory"]!.map((x) => WorkOrderHistory.fromJson(x))),
activities: json["activities"] == null ? [] : List<Activities>.from(json["activities"]!.map((x) => Activities.fromJson(x))), activities: json["activities"] == null ? [] : List<Activities>.from(json["activities"]!.map((x) => Activities.fromJson(x))),
needAVisitDateTime: DateTime.tryParse(json["needAVisitDateTime"] ?? ""), needAVisitDateTime: DateTime.tryParse(json["needAVisitDateTime"] ?? ""),
@ -281,7 +304,7 @@ class WorkOrderAssignedEmployee {
required this.languageId, required this.languageId,
}); });
dynamic userId; String userId;
String? userName; String? userName;
String? email; String? email;
int? languageId; int? languageId;
@ -357,7 +380,7 @@ class Activities {
activityStatus = json['activityStatus'] != null ? Lookup.fromJson(json['activityStatus']) : null; activityStatus = json['activityStatus'] != null ? Lookup.fromJson(json['activityStatus']) : null;
activityMaintenance = json['activityMaintenance'] != null ? ActivityMaintenance.fromJson(json['activityMaintenance']) : null; activityMaintenance = json['activityMaintenance'] != null ? ActivityMaintenance.fromJson(json['activityMaintenance']) : null;
if (activityMaintenance != null) { if (activityMaintenance != null) {
activityType = 'Maintenance Request'; activityType = 'CM Activity';
} }
activitySparePart = json['activitySparePart'] != null ? ActivitySparePart.fromJson(json['activitySparePart']) : null; activitySparePart = json['activitySparePart'] != null ? ActivitySparePart.fromJson(json['activitySparePart']) : null;
@ -504,9 +527,9 @@ class WorkOrderContactPerson {
String? name; String? name;
String? employeeId; String? employeeId;
String? position; String? position;
dynamic extension; String? extension;
String? email; String? email;
dynamic mobilePhone; String ?mobilePhone;
WorkOrderAssignedEmployee? contactUser; WorkOrderAssignedEmployee? contactUser;
factory WorkOrderContactPerson.fromJson(Map<String, dynamic> json) { factory WorkOrderContactPerson.fromJson(Map<String, dynamic> json) {
@ -619,6 +642,7 @@ class ActivityMaintenance {
String? supplierStartTime; String? supplierStartTime;
String? supplierEndTime; String? supplierEndTime;
double? supplierWorkingHours; double? supplierWorkingHours;
String? activityType;
List<ActivityMaintenanceAssistantEmployees>? assistantEmployees; List<ActivityMaintenanceAssistantEmployees>? assistantEmployees;
List<ActivityMaintenanceTimers>? activityMaintenanceTimers; List<ActivityMaintenanceTimers>? activityMaintenanceTimers;
@ -638,6 +662,7 @@ class ActivityMaintenance {
this.supplierEngineer, this.supplierEngineer,
this.supplierStartTime, this.supplierStartTime,
this.supplierEndTime, this.supplierEndTime,
this.activityType,
this.supplierWorkingHours, this.supplierWorkingHours,
this.assistantEmployees}); this.assistantEmployees});
@ -647,6 +672,7 @@ class ActivityMaintenance {
startTime = json['startTime']; startTime = json['startTime'];
endTime = json['endTime']; endTime = json['endTime'];
workingHours = json['workingHours']; workingHours = json['workingHours'];
activityType = json['activityType'];
travelHours = json['travelHours']; travelHours = json['travelHours'];
lastSituation = json['lastSituation'] != null ? Lookup.fromJson(json['lastSituation']) : null; lastSituation = json['lastSituation'] != null ? Lookup.fromJson(json['lastSituation']) : null;
repairLocation = json['repairLocation'] != null ? Lookup.fromJson(json['repairLocation']) : null; repairLocation = json['repairLocation'] != null ? Lookup.fromJson(json['repairLocation']) : null;

@ -3,6 +3,7 @@ import 'dart:io';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:test_sa/extensions/context_extension.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/lookup.dart';
import 'package:test_sa/models/service_request/supplier_details.dart'; import 'package:test_sa/models/service_request/supplier_details.dart';
import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/models/timer_model.dart';
@ -24,6 +25,8 @@ class PlanPreventiveVisit {
String? departmentName; String? departmentName;
String? roomName; String? roomName;
String? fromDate; String? fromDate;
String? creationDate;
String? closedDate;
String? toDate; String? toDate;
AssignedEmployee? assignedEmployee; AssignedEmployee? assignedEmployee;
DateTime? acutalDateOfVisit; DateTime? acutalDateOfVisit;
@ -65,6 +68,8 @@ class PlanPreventiveVisit {
this.departmentName, this.departmentName,
this.roomName, this.roomName,
this.fromDate, this.fromDate,
this.creationDate,
this.closedDate,
this.toDate, this.toDate,
this.assignedEmployee, this.assignedEmployee,
this.acutalDateOfVisit, this.acutalDateOfVisit,
@ -105,6 +110,8 @@ class PlanPreventiveVisit {
departmentName = json['departmentName']; departmentName = json['departmentName'];
roomName = json['roomName']; roomName = json['roomName'];
fromDate = json['fromDate']; fromDate = json['fromDate'];
creationDate = json['creationDate'];
closedDate = json['closedDate'];
toDate = json['toDate']; toDate = json['toDate'];
assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null; assignedEmployee = json['assignedEmployee'] != null ? AssignedEmployee.fromJson(json['assignedEmployee']) : null;
acutalDateOfVisit = json['acutalDateOfVisit'] != null ? DateTime.parse(json['acutalDateOfVisit']) : null; acutalDateOfVisit = json['acutalDateOfVisit'] != null ? DateTime.parse(json['acutalDateOfVisit']) : null;
@ -526,27 +533,27 @@ class PlanPreventiveVisit {
// } // }
// } // }
class Asset { // class Asset {
num? id; // num? id;
String? assetNumber; // String? assetNumber;
String? assetSerialNo; // String? assetSerialNo;
//
Asset({this.id, this.assetNumber, this.assetSerialNo}); // Asset({this.id, this.assetNumber, this.assetSerialNo});
//
Asset.fromJson(Map<String, dynamic> json) { // Asset.fromJson(Map<String, dynamic> json) {
id = json['id']; // id = json['id'];
assetNumber = json['assetNumber']; // assetNumber = json['assetNumber'];
assetSerialNo = json['assetSerialNo']; // assetSerialNo = json['assetSerialNo'];
} // }
//
Map<String, dynamic> toJson() { // Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>(); // final Map<String, dynamic> data = Map<String, dynamic>();
data['id'] = this.id; // data['id'] = this.id;
data['assetNumber'] = this.assetNumber; // data['assetNumber'] = this.assetNumber;
data['assetSerialNo'] = this.assetSerialNo; // data['assetSerialNo'] = this.assetSerialNo;
return data; // return data;
} // }
} // }
class AssignedEmployee { class AssignedEmployee {
String? userId; String? userId;
@ -776,136 +783,136 @@ class PreventiveVisitSuppliers {
} }
} }
class Supplier { // class Supplier {
int? id; // int? id;
String? suppliername; // String? suppliername;
String? name; // String? name;
String? website; // String? website;
String? email; // String? email;
String? code; // String? code;
int? suppNo; // int? suppNo;
String? suppStatusId; // String? suppStatusId;
String? cityId; // String? cityId;
String? person; // String? person;
String? comment; // String? comment;
String? zipcode; // String? zipcode;
String? contact; // String? contact;
List<String>? telephones; // List<String>? telephones;
List<String>? faxes; // List<String>? faxes;
List<String>? addresses; // List<String>? addresses;
List<String>? attachments; // List<String>? attachments;
List<SuppPersons>? suppPersons; // List<SuppPersons>? suppPersons;
List<String>? suppTCodes; // List<String>? suppTCodes;
//
Supplier( // Supplier(
{this.id, // {this.id,
this.suppliername, // this.suppliername,
this.name, // this.name,
this.website, // this.website,
this.email, // this.email,
this.code, // this.code,
this.suppNo, // this.suppNo,
this.suppStatusId, // this.suppStatusId,
this.cityId, // this.cityId,
this.person, // this.person,
this.comment, // this.comment,
this.zipcode, // this.zipcode,
this.contact, // this.contact,
this.telephones, // this.telephones,
this.faxes, // this.faxes,
this.addresses, // this.addresses,
this.attachments, // this.attachments,
this.suppPersons, // this.suppPersons,
this.suppTCodes}); // this.suppTCodes});
//
Supplier.fromJson(Map<String, dynamic> json) { // Supplier.fromJson(Map<String, dynamic> json) {
id = json['id']; // id = json['id'];
suppliername = json['suppliername']; // suppliername = json['suppliername'];
name = json['name']; // name = json['name'];
website = json['website']; // website = json['website'];
email = json['email']; // email = json['email'];
code = json['code']; // code = json['code'];
suppNo = json['suppNo']; // suppNo = json['suppNo'];
suppStatusId = json['suppStatusId']; // suppStatusId = json['suppStatusId'];
cityId = json['cityId']; // cityId = json['cityId'];
person = json['person']; // person = json['person'];
comment = json['comment']; // comment = json['comment'];
zipcode = json['zipcode']; // zipcode = json['zipcode'];
contact = json['contact']; // contact = json['contact'];
if (json['telephones'] != null) { // if (json['telephones'] != null) {
telephones = <String>[]; // telephones = <String>[];
json['telephones'].forEach((v) { // json['telephones'].forEach((v) {
telephones!.add(v); // telephones!.add(v);
}); // });
} // }
if (json['faxes'] != null) { // if (json['faxes'] != null) {
faxes = <String>[]; // faxes = <String>[];
json['faxes'].forEach((v) { // json['faxes'].forEach((v) {
faxes!.add(v); // faxes!.add(v);
}); // });
} // }
if (json['addresses'] != null) { // if (json['addresses'] != null) {
addresses = <String>[]; // addresses = <String>[];
json['addresses'].forEach((v) { // json['addresses'].forEach((v) {
addresses!.add(v); // addresses!.add(v);
}); // });
} // }
if (json['attachments'] != null) { // if (json['attachments'] != null) {
attachments = <String>[]; // attachments = <String>[];
json['attachments'].forEach((v) { // json['attachments'].forEach((v) {
attachments!.add(v); // attachments!.add(v);
}); // });
} // }
if (json['suppPersons'] != null) { // if (json['suppPersons'] != null) {
suppPersons = <SuppPersons>[]; // suppPersons = <SuppPersons>[];
json['suppPersons'].forEach((v) { // json['suppPersons'].forEach((v) {
suppPersons!.add(SuppPersons.fromJson(v)); // suppPersons!.add(SuppPersons.fromJson(v));
}); // });
} // }
if (json['suppTCodes'] != null) { // if (json['suppTCodes'] != null) {
suppTCodes = <String>[]; // suppTCodes = <String>[];
json['suppTCodes'].forEach((v) { // json['suppTCodes'].forEach((v) {
suppTCodes!.add(v); // suppTCodes!.add(v);
}); // });
} // }
} // }
//
Map<String, dynamic> toJson() { // Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{}; // final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id; // data['id'] = id;
data['suppliername'] = suppliername; // data['suppliername'] = suppliername;
data['name'] = name; // data['name'] = name;
data['website'] = website; // data['website'] = website;
data['email'] = email; // data['email'] = email;
data['code'] = code; // data['code'] = code;
data['suppNo'] = suppNo; // data['suppNo'] = suppNo;
data['suppStatusId'] = suppStatusId; // data['suppStatusId'] = suppStatusId;
data['cityId'] = cityId; // data['cityId'] = cityId;
data['person'] = person; // data['person'] = person;
data['comment'] = comment; // data['comment'] = comment;
data['zipcode'] = zipcode; // data['zipcode'] = zipcode;
data['contact'] = contact; // data['contact'] = contact;
if (telephones != null) { // if (telephones != null) {
data['telephones'] = telephones!.map((v) => v).toList(); // data['telephones'] = telephones!.map((v) => v).toList();
} // }
if (faxes != null) { // if (faxes != null) {
data['faxes'] = faxes!.map((v) => v).toList(); // data['faxes'] = faxes!.map((v) => v).toList();
} // }
if (addresses != null) { // if (addresses != null) {
data['addresses'] = addresses!.map((v) => v).toList(); // data['addresses'] = addresses!.map((v) => v).toList();
} // }
if (attachments != null) { // if (attachments != null) {
data['attachments'] = attachments!.map((v) => v).toList(); // data['attachments'] = attachments!.map((v) => v).toList();
} // }
if (suppPersons != null) { // if (suppPersons != null) {
data['suppPersons'] = suppPersons!.map((v) => v.toJson()).toList(); // data['suppPersons'] = suppPersons!.map((v) => v.toJson()).toList();
} // }
if (suppTCodes != null) { // if (suppTCodes != null) {
data['suppTCodes'] = suppTCodes!.map((v) => v).toList(); // data['suppTCodes'] = suppTCodes!.map((v) => v).toList();
} // }
return data; // return data;
} // }
} // }
// class SuppPersons { // class SuppPersons {
// int? id; // int? id;
@ -949,14 +956,14 @@ class PreventiveVisitKits {
PreventiveVisitKits.fromJson(Map<String, dynamic> json) { PreventiveVisitKits.fromJson(Map<String, dynamic> json) {
id = json['id']; id = json['id'];
partCatalogItem = json['partCatalogItem'] != null ? PartCatalogItem.fromJson(json['partCatalogItem']) : null; partCatalogItem = json['partCatalogItem'] != null ? PartCatalogItem.fromJson(json['partCatalogItem']) : null;
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>(); final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id; data['id'] = id;
if (partCatalogItem != null) { if (partCatalogItem != null) {
// data['partCatalogItem'] = partCatalogItem!.toJson();
data['partCatalogItemId'] = partCatalogItem?.id; data['partCatalogItemId'] = partCatalogItem?.id;
} }
return data; return data;

@ -53,6 +53,7 @@ class RecurrentWoData {
TimerModel? recurrentWoTimerModel = TimerModel(); TimerModel? recurrentWoTimerModel = TimerModel();
double? totalWorkingHours = 0.0; double? totalWorkingHours = 0.0;
List<TimerModel>? timerModelList = []; List<TimerModel>? timerModelList = [];
String? comment;
RecurrentWoData( RecurrentWoData(
{this.id, {this.id,
@ -70,6 +71,7 @@ class RecurrentWoData {
this.planRecurrentMedicalTaskRooms, this.planRecurrentMedicalTaskRooms,
this.planRecurrentTaskTimers, this.planRecurrentTaskTimers,
this.timerModelList, this.timerModelList,
this.comment,
this.totalWorkingHours}); this.totalWorkingHours});
RecurrentWoData.fromJson(Map<String, dynamic> json) { RecurrentWoData.fromJson(Map<String, dynamic> json) {
@ -84,6 +86,7 @@ class RecurrentWoData {
floor = json["floor"] == null ? null : Lookup.fromJson(json["floor"]); floor = json["floor"] == null ? null : Lookup.fromJson(json["floor"]);
department = json["department"] == null ? null : Lookup.fromJson(json["department"]); department = json["department"] == null ? null : Lookup.fromJson(json["department"]);
room = json["room"] == null ? null : Lookup.fromJson(json["room"]); room = json["room"] == null ? null : Lookup.fromJson(json["room"]);
comment = json["comment"];
if (json['planRecurrentMedicalTaskRooms'] != null) { if (json['planRecurrentMedicalTaskRooms'] != null) {
planRecurrentMedicalTaskRooms = <PlanRecurrentMedicalTaskRooms>[]; planRecurrentMedicalTaskRooms = <PlanRecurrentMedicalTaskRooms>[];
json['planRecurrentMedicalTaskRooms'].forEach((v) { json['planRecurrentMedicalTaskRooms'].forEach((v) {
@ -114,6 +117,7 @@ class RecurrentWoData {
} }
data['id'] = id; data['id'] = id;
data['statusValue'] = status; data['statusValue'] = status;
data['comment'] = comment;
if (planRecurrentTaskTimers != null) { if (planRecurrentTaskTimers != null) {
data['planRecurrentTaskTimers'] = planRecurrentTaskTimers!.map((v) => v.toJson()).toList(); data['planRecurrentTaskTimers'] = planRecurrentTaskTimers!.map((v) => v.toJson()).toList();
@ -289,7 +293,7 @@ class PlanRecurrentMedicalTaskRoomTabAttributes {
PlanRecurrentMedicalTaskRoomTabAttributes.fromJson(Map<String, dynamic> json) { PlanRecurrentMedicalTaskRoomTabAttributes.fromJson(Map<String, dynamic> json) {
id = json['id']; id = json['id'];
attribute = json['attribute'] != null ? Attribute.fromJson(json['attribute']) : null; 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<String, dynamic> toJson() { Map<String, dynamic> toJson() {

@ -5,7 +5,7 @@ class SparePartsWorkOrders extends Base {
SparePartsWorkOrders.fromJson(dynamic json) { SparePartsWorkOrders.fromJson(dynamic json) {
id = json['id']; 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']; qty = json['qty'];
returnQty = json['returnQty']; returnQty = json['returnQty'];
@ -40,35 +40,84 @@ class SparePart extends Base {
this.partNo, this.partNo,
this.partName, this.partName,
this.oracleCode, this.oracleCode,
this.displayName,
this.assetId, this.assetId,
}) : super(identifier: id?.toString(), name: partName); }) : super(identifier: id?.toString(), name: partName);
SparePart.fromJson(dynamic json) { SparePart.fromJson(dynamic json,bool ?isDisplayName) {
id = json['id']; id = json['id'];
identifier = id?.toString(); identifier = id?.toString();
partNo = json['partNo']; partNo = json['partNo'];
partName = json['partName']; partName = json['partName'];
displayName = json['displayName'];
oracleCode = json['oracleCode']; oracleCode = json['oracleCode'];
name = partName; name = isDisplayName!=null&&isDisplayName?displayName: partName;
assetId = json['assetId']; assetId = json['assetId'];
} }
num? id; num? id;
String? partNo; String? partNo;
String? partName; String? partName;
String? displayName;
String? oracleCode; String? oracleCode;
num? assetId; num? assetId;
SparePart copyWith({num? id, String? partNo, String? partName, num? assetId,String?oracleCode}) => 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); 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<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final map = <String, dynamic>{}; final map = <String, dynamic>{};
map['id'] = id; map['id'] = id;
map['partNo'] = partNo; map['partNo'] = partNo;
map['partName'] = partName; map['partName'] = partName;
map['displayName'] = displayName;
map['oracleCode'] = oracleCode; map['oracleCode'] = oracleCode;
map['assetId'] = assetId; map['assetId'] = assetId;
return map; 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<String, dynamic> 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<String, dynamic> toJson() {
return {
'id': id,
'storeId': storeId,
'availablityQty': availablityQty,
'siteName': siteName,
'storeName': storeName,
'requestedQty': requestedQty,
'alreadyRequestFromThisStore': alreadyRequestFromThisStore,
};
}
}

@ -47,6 +47,7 @@ class AppColor {
static const Color white60 = Color(0xffEFEFEF); static const Color white60 = Color(0xffEFEFEF);
static const Color white70 = Color(0xffF1F1F1); static const Color white70 = Color(0xffF1F1F1);
static const Color white80 = Color(0xffF2F4FA); static const Color white80 = Color(0xffF2F4FA);
static const Color white90 = Color(0xffBFD1E4);
static const Color white936 = Color(0xff212936); static const Color white936 = Color(0xff212936);
//black //black
@ -79,6 +80,7 @@ class AppColor {
static const Color orange50 = Color(0xffCC9B14); static const Color orange50 = Color(0xffCC9B14);
static const Color orange60 = Color(0xff886400); static const Color orange60 = Color(0xff886400);
static const Color orange70 = Color(0xffFFC945); 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(0xff1FA269) : green50;
static Color greenStatus(BuildContext context) => context.isDark ? const Color(0xff54C166) : green70.withOpacity(.5); static Color greenStatus(BuildContext context) => context.isDark ? const Color(0xff54C166) : green70.withOpacity(.5);
@ -136,6 +138,27 @@ class AppColor {
return Colors.white; 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) { static Color getHistoryLogStatusColorByName(String status) {
switch ((status).toLowerCase()) { switch ((status).toLowerCase()) {

@ -15,6 +15,7 @@ class AppFilledButton extends StatelessWidget {
final Color? textColor; final Color? textColor;
final bool showBorder; final bool showBorder;
final double radius; final double radius;
final int height;
final bool disableButton; final bool disableButton;
const AppFilledButton( const AppFilledButton(
@ -25,6 +26,7 @@ class AppFilledButton extends StatelessWidget {
this.icon, this.icon,
this.fontSize, this.fontSize,
this.loading = false, this.loading = false,
this.height = 56,
this.showBorder = false, this.showBorder = false,
this.disableButton = false, this.disableButton = false,
this.buttonColor, this.buttonColor,
@ -36,7 +38,7 @@ class AppFilledButton extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
height: 56.toScreenHeight, height: height.toScreenHeight,
width: maxWidth ? double.infinity : null, width: maxWidth ? double.infinity : null,
alignment: Alignment.center, alignment: Alignment.center,
decoration: BoxDecoration( decoration: BoxDecoration(

@ -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/enums/user_types.dart';
import 'package:test_sa/models/user.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/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 'package:test_sa/views/pages/user/requests/create_service_request_page.dart';
import '../app_style/app_color.dart'; import '../app_style/app_color.dart';
@ -40,7 +40,7 @@ class _AppFloatingActionButtonState extends State<AppFloatingActionButton> {
final elements = [ final elements = [
if (user.type == UsersTypes.normal_user) fabItem(context.translation.gasRefillRequest, "gas_refill_request", NewGasRefillRequestPage.routeName), 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) 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) const Divider().defaultStyle(context).paddingOnly(top: 16, bottom: 16),
if (user.type == UsersTypes.normal_user) fabItem(context.translation.serviceRequest, "service_request", CreateServiceRequestPage.id), if (user.type == UsersTypes.normal_user) fabItem(context.translation.serviceRequest, "service_request", CreateServiceRequestPage.id),
]; ];

@ -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/text_extensions.dart';
import 'package:test_sa/extensions/widget_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/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'; import '../app_style/app_color.dart';
@ -12,8 +13,10 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
final List<Widget>? actions; final List<Widget>? actions;
final Function? onBackPress; final Function? onBackPress;
final bool showHomeActionButton; 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -40,6 +43,18 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
title: Row( title: Row(
children: [ children: [
const Icon(Icons.arrow_back_ios).onPress(() { 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) { if (onBackPress != null) {
onBackPress!(); onBackPress!();
} else { } else {
@ -49,7 +64,7 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
10.width, 10.width,
Text( Text(
title ?? "", 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, ).expanded,
], ],
), ),

@ -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/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/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/user/tasks_request/create_task_view.dart';
import 'package:test_sa/views/pages/device_transfer/create__asset_transfer_request.dart';
class CreateRequestTypeBottomSheet extends StatelessWidget { class CreateRequestTypeBottomSheet extends StatelessWidget {
final bool isEngineer; final bool isEngineer;
@ -65,7 +66,7 @@ class CreateRequestTypeBottomSheet extends StatelessWidget {
icon: 'add_icon', icon: 'add_icon',
label: context.translation.deviceTransfer, label: context.translation.deviceTransfer,
onTap: () async { onTap: () async {
Navigator.pushReplacementNamed(context, RequestDeviceTransfer.id); Navigator.pushReplacementNamed(context, CreateAssetTransferRequest.id);
}, },
), ),
listCard( listCard(

@ -1,9 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.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/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_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/models/search_all_requests_model.dart';
import 'package:test_sa/new_views/app_style/app_color.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_filled_button.dart';
@ -43,6 +45,7 @@ class _AllRequestsFilterPageState extends State<AllRequestsFilterPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
bool isEngineer = (Provider.of<UserProvider>(context, listen: false).user?.type) == UsersTypes.engineer;
if (search == null) { if (search == null) {
search = SearchAllRequestsModel( search = SearchAllRequestsModel(
requestNumber: SearchByRequestNumberModel(context, controller: TextEditingController()), requestNumber: SearchByRequestNumberModel(context, controller: TextEditingController()),
@ -59,14 +62,17 @@ class _AllRequestsFilterPageState extends State<AllRequestsFilterPage> {
context.translation.gasRefill: 2, context.translation.gasRefill: 2,
context.translation.deviceTransfer: 3, context.translation.deviceTransfer: 3,
context.translation.preventiveMaintenance: 4, context.translation.preventiveMaintenance: 4,
context.translation.recurrentWo: 5,
}; };
if (isEngineer) {
types.addAll({context.translation.recurrentWo: 5});
}
final statuses = { final statuses = {
context.translation.allRequests: 0, "All WO": 0,
context.translation.open: 1, context.translation.open: 1,
context.translation.inProgress: 2, context.translation.inProgress: 2,
context.translation.completed: 4, context.translation.completed: 4,
context.translation.closed: 3, context.translation.closed: 3,
"Canceled": 5,
}; };
return Scaffold( return Scaffold(
appBar: DefaultAppBar( appBar: DefaultAppBar(
@ -99,7 +105,7 @@ class _AllRequestsFilterPageState extends State<AllRequestsFilterPage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
context.translation.requestStatus.heading5(context), "WO Status".heading5(context),
8.height, 8.height,
RequestsTypeFilter( RequestsTypeFilter(
initialValues: search?.statuses ?? [], initialValues: search?.statuses ?? [],
@ -116,7 +122,7 @@ class _AllRequestsFilterPageState extends State<AllRequestsFilterPage> {
}, },
), ),
16.height, 16.height,
context.translation.typeOfRequest.heading5(context), "Type of WO".heading5(context),
8.height, 8.height,
RequestsTypeFilter( RequestsTypeFilter(
initialValues: search?.typeTransaction ?? [], initialValues: search?.typeTransaction ?? [],
@ -155,25 +161,25 @@ class _AllRequestsFilterPageState extends State<AllRequestsFilterPage> {
], ],
), ),
16.height, 16.height,
"Archived Requests".heading5(context), // "Archived WO".heading5(context),
// 8.height, // // 8.height,
Row( // Row(
children: [ // children: [
Checkbox( // Checkbox(
value: search?.isArchived ?? false, // value: search?.isArchived ?? false,
activeColor: AppColor.blueStatus(context), // activeColor: AppColor.blueStatus(context),
onChanged: (value) { // onChanged: (value) {
if (search?.isArchived != value) { // if (search?.isArchived != value) {
search?.isArchived = value!; // search?.isArchived = value!;
} // }
if (mounted) setState(() {}); // if (mounted) setState(() {});
}), // }),
"View Archived Requests".bodyText(context).expanded, // "View Archived Requests".bodyText(context).expanded,
], // ],
).onPress(() { // ).onPress(() {
search?.isArchived = !search!.isArchived; // search?.isArchived = !search!.isArchived;
setState(() {}); // setState(() {});
}), // }),
], ],
).paddingOnly(start: 16, end: 16), ).paddingOnly(start: 16, end: 16),
).expanded, ).expanded,

@ -21,7 +21,9 @@ class GasRefillItemView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (requestData != null) { if (requestData != null) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [

@ -49,10 +49,11 @@ class PpmItemView extends StatelessWidget {
8.height, 8.height,
(requestData?.typeTransaction ?? context.translation.ppmRequest).heading5(context), (requestData?.typeTransaction ?? context.translation.ppmRequest).heading5(context),
8.height, 8.height,
'${context.translation.assetName}: ${requestData!.assetName}'.bodyText(context),
'${context.translation.assetNumber}: ${requestData!.assetNumber}'.bodyText(context), '${context.translation.assetNumber}: ${requestData!.assetNumber}'.bodyText(context),
// '${context.translation.assetSN}: ${request.assetSN}'.bodyText(context),//todo ask ahmed // '${context.translation.assetSN}: ${request.assetSN}'.bodyText(context),//todo ask ahmed
// '${context.translation.code}: ${request.code}'.bodyText(context), // '${context.translation.code}: ${request.code}'.bodyText(context),
'${context.translation.requestNo}: ${requestData!.requestNo}'.bodyText(context), 'PM No: ${requestData!.requestNo}'.bodyText(context),
16.height, 16.height,
Row( Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@ -99,10 +100,11 @@ class PpmItemView extends StatelessWidget {
8.height, 8.height,
(requestDetails?.nameOfType ?? context.translation.ppmRequest).heading5(context), (requestDetails?.nameOfType ?? context.translation.ppmRequest).heading5(context),
8.height, 8.height,
'${context.translation.assetName}: ${requestDetails!.assetName}'.bodyText(context),
'${context.translation.assetNumber}: ${requestDetails!.assetNo}'.bodyText(context), '${context.translation.assetNumber}: ${requestDetails!.assetNo}'.bodyText(context),
'${context.translation.assetSN}: ${requestDetails!.assetSN}'.bodyText(context), '${context.translation.assetSN}: ${requestDetails!.assetSN}'.bodyText(context),
// '${context.translation.code}: ${request.code}'.bodyText(context), // '${context.translation.code}: ${request.code}'.bodyText(context),
'${context.translation.requestNo}: ${requestDetails!.requestNo}'.bodyText(context), 'PM No: ${requestDetails!.requestNo}'.bodyText(context),
16.height, 16.height,
Row( Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,

@ -52,7 +52,7 @@ class RecurrentWoItemView extends StatelessWidget {
// '${context.translation.assetNumber}: ${requestData!.assetNumber}'.bodyText(context), // '${context.translation.assetNumber}: ${requestData!.assetNumber}'.bodyText(context),
// '${context.translation.assetSN}: ${request.assetSN}'.bodyText(context),//todo ask ahmed // '${context.translation.assetSN}: ${request.assetSN}'.bodyText(context),//todo ask ahmed
// '${context.translation.code}: ${request.code}'.bodyText(context), // '${context.translation.code}: ${request.code}'.bodyText(context),
'${context.translation.requestNo}: ${requestData!.requestNo}'.bodyText(context), '${context.translation.taskNo}: ${requestData!.requestNo}'.bodyText(context),
16.height, 16.height,
Row( Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@ -102,7 +102,7 @@ class RecurrentWoItemView extends StatelessWidget {
// '${context.translation.taskNo}: ${requestDetails!.id}'.bodyText(context), // '${context.translation.taskNo}: ${requestDetails!.id}'.bodyText(context),
'${context.translation.site}: ${requestDetails!.site}'.bodyText(context), '${context.translation.site}: ${requestDetails!.site}'.bodyText(context),
// '${context.translation.code}: ${request.code}'.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, 16.height,
Row( Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,

@ -52,12 +52,14 @@ class ServiceRequestItemView extends StatelessWidget {
8.height, 8.height,
(requestData?.typeTransaction ?? context.translation.correctiveMaintenance).heading5(context), (requestData?.typeTransaction ?? context.translation.correctiveMaintenance).heading5(context),
8.height, 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.assetNumber}: ${request.assetNo}'.bodyText(context),
// '${context.translation.requestType}: ${requestData!.requestTypeName}'.bodyText(context), // '${context.translation.requestType}: ${requestData!.requestTypeName}'.bodyText(context),
'${context.translation.requestNo}: ${requestData!.requestNo}'.bodyText(context),
if (requestData?.statusName == 'Canceled') ...[ if (requestData?.statusName == 'Canceled') ...[
'${context.translation.rejectionReason}: ${requestData!.rejectReason}'.bodyText(context), '${context.translation.rejectionReason}: ${requestData?.rejectReason}'.bodyText(context),
], ],
8.height, 8.height,
Row( Row(
@ -110,10 +112,11 @@ class ServiceRequestItemView extends StatelessWidget {
8.height, 8.height,
(requestDetails!.nameOfType ?? context.translation.correctiveMaintenance).heading5(context), (requestDetails!.nameOfType ?? context.translation.correctiveMaintenance).heading5(context),
8.height, 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.assetNumber}: ${requestDetails!.assetNo}'.bodyText(context),
'${context.translation.requestType}: ${requestDetails!.requestType}'.bodyText(context), '${context.translation.assetName}: ${requestDetails!.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context),
'${context.translation.requestNo}: ${requestDetails!.requestNo}'.bodyText(context),
8.height, 8.height,
Row( Row(
// mainAxisSize: MainAxisSize.min, // mainAxisSize: MainAxisSize.min,

@ -1,7 +1,10 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.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/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_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/models/new_models/site.dart';
import 'package:test_sa/new_views/app_style/app_color.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_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/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_size_provider.dart';
import 'package:test_sa/providers/gas_request_providers/cylinder_type_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/gas_types_provider.dart';
import 'package:test_sa/providers/gas_request_providers/site_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/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 '../../controllers/providers/api/gas_refill_provider.dart';
import '../common_widgets/default_app_bar.dart'; import '../common_widgets/default_app_bar.dart';
@ -36,6 +44,9 @@ class _NewGasRefillRequestPageState extends State<NewGasRefillRequestPage> {
late GasRefillDetails _currentDetails; late GasRefillDetails _currentDetails;
late GasRefillModel _gasModel; late GasRefillModel _gasModel;
Lookup? _requestedQuantity; Lookup? _requestedQuantity;
final TextEditingController _commentController = TextEditingController();
GasRefillProvider? _gasRefillProvider;
List<File> _files = [];
static List<Lookup> gasQuantity = [ static List<Lookup> gasQuantity = [
Lookup(name: "1", id: 1, value: 1), Lookup(name: "1", id: 1, value: 1),
@ -48,8 +59,10 @@ class _NewGasRefillRequestPageState extends State<NewGasRefillRequestPage> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_gasRefillProvider ??= Provider.of<GasRefillProvider>(context, listen: false);
_gasModel =GasRefillModel();
_currentDetails = GasRefillDetails(); _currentDetails = GasRefillDetails();
_gasModel = GasRefillModel(gazRefillDetails: []); _gasModel = GasRefillModel(gasRefillDetails: []);
} }
@override @override
@ -59,39 +72,33 @@ class _NewGasRefillRequestPageState extends State<NewGasRefillRequestPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: DefaultAppBar(title: context.translation.newGasRefillRequest), appBar: DefaultAppBar(title: context.translation.newGasRefillRequest),
body: Column( body: Column(
children: [ children: [
12.height,
SingleChildScrollView( SingleChildScrollView(
child: Column( child: Column(
children: [ children: [
16.height,
SingleItemDropDownMenu<Lookup, GasTypesProvider>( SingleItemDropDownMenu<Lookup, GasTypesProvider>(
context: context, context: context,
title: context.translation.gasType, title: context.translation.gasType,
initialValue: _currentDetails.gasType, initialValue: _currentDetails.gasType,
backgroundColor: AppColor.neutral100,
showShadow: false,
showAsBottomSheet: true, showAsBottomSheet: true,
onSelect: (value) { onSelect: (value) {
_currentDetails.gasType = value; _currentDetails.gasType = value;
}, },
), ),
8.height, 8.height,
SingleItemDropDownMenu<Lookup, NullableLoadingProvider>(
context: context,
title: context.translation.quantity,
initialValue: _requestedQuantity,
staticData: gasQuantity,
onSelect: (value) {
_requestedQuantity = value;
_currentDetails.requestedQty = value?.value;
},
),
8.height,
SingleItemDropDownMenu<Lookup, CylinderTypesProvider>( SingleItemDropDownMenu<Lookup, CylinderTypesProvider>(
context: context, context: context,
title: context.translation.cylinderType, title: context.translation.cylinderType,
initialValue: _currentDetails.cylinderType, initialValue: _currentDetails.cylinderType,
backgroundColor: AppColor.neutral100,
showShadow: false,
onSelect: (value) { onSelect: (value) {
_currentDetails.cylinderType = value; _currentDetails.cylinderType = value;
}, },
@ -102,136 +109,153 @@ class _NewGasRefillRequestPageState extends State<NewGasRefillRequestPage> {
title: context.translation.cylinderSize, title: context.translation.cylinderSize,
initialValue: _currentDetails.cylinderSize, initialValue: _currentDetails.cylinderSize,
showAsBottomSheet: true, showAsBottomSheet: true,
backgroundColor: AppColor.neutral100,
showShadow: false,
onSelect: (value) { onSelect: (value) {
_currentDetails.cylinderSize = value; _currentDetails.cylinderSize = value;
}, },
), ),
8.height, 8.height,
SingleItemDropDownMenu<Site, SiteProvider>( SingleItemDropDownMenu<Lookup, NullableLoadingProvider>(
context: context, context: context,
title: context.translation.site, title: context.translation.quantity,
initialValue: _gasModel.site,
showAsBottomSheet: true, showAsBottomSheet: true,
initialValue: _requestedQuantity,
staticData: gasQuantity,
backgroundColor: AppColor.neutral100,
showShadow: false,
onSelect: (value) { onSelect: (value) {
setState(() { _requestedQuantity = value;
_gasModel.site = value; _currentDetails.requestedQty = value?.value;
_gasModel.building = null;
_gasModel.floor = null;
_gasModel.department = null;
});
}, },
), ),
8.height, 8.height,
SingleItemDropDownMenu<Building, NullableLoadingProvider>( Row(
context: context, children: [
title: context.translation.building, SingleItemDropDownMenu<Site, SiteProvider>(
initialValue: _gasModel.building, context: context,
enabled: _gasModel.site?.buildings?.isNotEmpty ?? false, title: context.translation.site,
staticData: _gasModel.site?.buildings ?? [], initialValue: _gasModel.site,
showAsBottomSheet: true, showAsBottomSheet: true,
onSelect: (value) { backgroundColor: AppColor.neutral100,
setState(() { showShadow: false,
_gasModel.building = value; onSelect: (value) {
_gasModel.floor = null; setState(() {
_gasModel.department = null; _gasModel.site = value;
}); _gasModel.building = null;
}, _gasModel.floor = null;
_gasModel.department = null;
});
},
).expanded,
8.width,
SingleItemDropDownMenu<Building, NullableLoadingProvider>(
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, 8.height,
SingleItemDropDownMenu<Floor, NullableLoadingProvider>( Row(
context: context, children: [
title: context.translation.floor, SingleItemDropDownMenu<Floor, NullableLoadingProvider>(
initialValue: _gasModel.floor, context: context,
enabled: _gasModel.building?.floors?.isNotEmpty ?? false, title: context.translation.floor,
staticData: _gasModel.building?.floors ?? [], initialValue: _gasModel.floor,
showAsBottomSheet: true, enabled: _gasModel.building?.floors?.isNotEmpty ?? false,
onSelect: (value) { staticData: _gasModel.building?.floors ?? [],
setState(() { showAsBottomSheet: true,
_gasModel.floor = value; backgroundColor: AppColor.neutral100,
_gasModel.department = null; showShadow: false,
}); onSelect: (value) {
}, setState(() {
_gasModel.floor = value;
_gasModel.department = null;
});
},
).expanded,
8.width,
SingleItemDropDownMenu<Department, NullableLoadingProvider>(
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, 8.height,
SingleItemDropDownMenu<Department, NullableLoadingProvider>( AppTextFormField(
context: context, labelText: context.translation.callComments,
title: context.translation.department, labelStyle: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral120),
initialValue: _gasModel.department, textInputType: TextInputType.multiline,
enabled: _gasModel.floor?.departments?.isNotEmpty ?? false, alignLabelWithHint: true,
staticData: _gasModel.floor?.departments ?? [], backgroundColor: AppColor.neutral100,
showAsBottomSheet: true, showShadow: false,
onSelect: (value) { controller: _commentController,
_gasModel.department = value; onChange: (value){
_gasModel.comment = value;
}, },
onSaved: (value) {},
), ),
8.height, 8.height,
if (_gasModel.gazRefillDetails?.isEmpty ?? true) MultiFilesPicker(
AppFilledButton( label: context.translation.attachFiles,
label: context.translation.add, files:_files,
maxWidth: true, buttonColor: AppColor.black10,
textColor: Colors.white, onlyImages: false,
buttonColor: context.isDark ? AppColor.neutral60 : AppColor.neutral50, buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120),
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);
},
), ),
], ],
), ).toShadowContainer(context, padding: 10).paddingOnly(start: 16, end: 16, top: 16),
).expanded, ).expanded,
16.height, 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<void> _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 { void _add() async {
if (_currentDetails.validate(context) && _gasModel.validate(context)) { if (_currentDetails.validate(context) && _gasModel.validate(context)) {
_gasModel.gazRefillDetails!.add(_currentDetails); _gasModel.gasRefillDetails!.add(_currentDetails);
_currentDetails = GasRefillDetails(); _currentDetails = GasRefillDetails();
_requestedQuantity = null; _requestedQuantity = null;
setState(() {}); setState(() {});
@ -239,19 +263,62 @@ class _NewGasRefillRequestPageState extends State<NewGasRefillRequestPage> {
} }
void _delete(index) { void _delete(index) {
_gasModel.gazRefillDetails!.remove(_gasModel.gazRefillDetails![index]); _gasModel.gasRefillDetails!.remove(_gasModel.gasRefillDetails![index]);
setState(() {}); setState(() {});
} }
//older code....
Future<void> _submit() async { // if (_gasModel.gasRefillDetails?.isEmpty ?? true)
if (_gasModel.gazRefillDetails?.isEmpty ?? true) { // AppFilledButton(
Fluttertoast.showToast(msg: context.translation.youHaveToAddRequests); // label: context.translation.add,
return; // maxWidth: true,
} // textColor: Colors.white,
await Provider.of<GasRefillProvider>(context, listen: false).createModel( // buttonColor: context.isDark ? AppColor.neutral60 : AppColor.neutral50,
context: context, // onPressed: _add,
user: Provider.of<UserProvider>(context, listen: false).user!, // ),
model: _gasModel, // 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);
// },
// ),
} }

@ -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,
],
),
],
),
),
);
}
}

@ -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'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
class ConfirmDialog extends StatelessWidget { class ConfirmDialog extends StatelessWidget {
final String ?title; final String? title;
final String ?message; final String? message;
final String ?okTitle; final String? okTitle;
final VoidCallback ?onTap; final VoidCallback? onTap;
final VoidCallback ?onCloseTap; 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 @override
Widget build(BuildContext context) { 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, 28.height,
AppFilledButton( AppFilledButton(
label: okTitle ?? "OK", label: okTitle ?? "OK",

@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:developer'; import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:http/src/response.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/arrival_verification_type_model.dart';
import 'package:test_sa/models/new_models/dashboard_detail.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/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/models/service_request/supplier_details.dart';
import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart';
class ServiceRequestDetailProvider extends ChangeNotifier { class ServiceRequestDetailProvider extends ChangeNotifier {
final pageItemNumber = 10; final pageItemNumber = 10;
@ -102,6 +105,15 @@ class ServiceRequestDetailProvider extends ChangeNotifier {
AssetRetiredHelperModel? assetRetiredHelperModel = AssetRetiredHelperModel(); AssetRetiredHelperModel? assetRetiredHelperModel = AssetRetiredHelperModel();
ActivityMaintenanceHelperModel? activityMaintenanceHelperModel = ActivityMaintenanceHelperModel(); ActivityMaintenanceHelperModel? activityMaintenanceHelperModel = ActivityMaintenanceHelperModel();
SparePartHelperModel? sparePartHelperModel; SparePartHelperModel? sparePartHelperModel;
List<StoreAvailability> _storeAvailability= [];
List<StoreAvailability> get storeAvailability => _storeAvailability;
set storeAvailability(List<StoreAvailability> value) {
_storeAvailability = value;
notifyListeners();
}
FixRemotelyHelperModel? fixRemotelyHelperModel = FixRemotelyHelperModel(); FixRemotelyHelperModel? fixRemotelyHelperModel = FixRemotelyHelperModel();
NeedVisitHelperModel? needVisitHelperModel = NeedVisitHelperModel(); NeedVisitHelperModel? needVisitHelperModel = NeedVisitHelperModel();
NurseActionHelperModel? nurseActionHelperModel; NurseActionHelperModel? nurseActionHelperModel;
@ -183,7 +195,15 @@ class ServiceRequestDetailProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
//create workOrder nurse ..... bool _isReadOnlyRequest = false;
bool get isReadOnlyRequest => _isReadOnlyRequest;
set isReadOnlyRequest(bool value) {
_isReadOnlyRequest = value;
notifyListeners();
} //create workOrder nurse .....
Future<int> createWorkOrder() async { Future<int> createWorkOrder() async {
isLoading = true; isLoading = true;
notifyListeners(); notifyListeners();
@ -213,6 +233,39 @@ class ServiceRequestDetailProvider extends ChangeNotifier {
notifyListeners(); notifyListeners();
final response = await ApiManager.instance.get(URLs.getWorkOrderByIdUrl + "?workOrderId=$id"); final response = await ApiManager.instance.get(URLs.getWorkOrderByIdUrl + "?workOrderId=$id");
stateCode = response.statusCode; 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<File> attachments}) async {
try {
List<WorkOrderAttachments> 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) { if (response.statusCode >= 200 && response.statusCode < 300) {
currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body)); currentWorkOrder = WorkOrderDetail.fromJson(json.decode(response.body));
} }
@ -700,6 +753,33 @@ class ServiceRequestDetailProvider extends ChangeNotifier {
} }
} }
Future<void> 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<dynamic> 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<int> deleteActivitySparePart({required int id, required int workOrderId}) async { Future<int> deleteActivitySparePart({required int id, required int workOrderId}) async {
isLoading = true; isLoading = true;
notifyListeners(); notifyListeners();

@ -457,7 +457,6 @@ class ConfirmArrivalNotificationModel {
this.accept, this.accept,
}); });
// Factory constructor to create an instance from a Map (e.g., JSON)
factory ConfirmArrivalNotificationModel.fromJson(Map<String, dynamic> json) { factory ConfirmArrivalNotificationModel.fromJson(Map<String, dynamic> json) {
return ConfirmArrivalNotificationModel( return ConfirmArrivalNotificationModel(
transactionType: json['transactionType'], transactionType: json['transactionType'],

@ -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/user_types.dart';
import 'package:test_sa/models/enums/work_order_next_step.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/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/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/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_filled_button.dart';
@ -34,10 +35,10 @@ class FooterActionButton {
{required WorkOrderNextStepEnum workOrderNextStepStatus, {required WorkOrderNextStepEnum workOrderNextStepStatus,
List<Activities> activities = const [], List<Activities> activities = const [],
required BuildContext context, required BuildContext context,
Lookup? status,
required UserProvider userProvider, required UserProvider userProvider,
bool isEmpIsAssigned = false}) { bool isEmpIsAssigned = false}) {
ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false); ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
bool showMarkAsFixedButton = activities.isEmpty ? false : activities.any((object) => object.activityStatus!.value == 14 || object.activityStatus!.value == 19); bool showMarkAsFixedButton = activities.isEmpty ? false : activities.any((object) => object.activityStatus!.value == 14 || object.activityStatus!.value == 19);
if (userProvider.user?.type == UsersTypes.engineer) { if (userProvider.user?.type == UsersTypes.engineer) {
if (workOrderNextStepStatus == WorkOrderNextStepEnum.assignToMe && isEmpIsAssigned) return const SizedBox(); if (workOrderNextStepStatus == WorkOrderNextStepEnum.assignToMe && isEmpIsAssigned) return const SizedBox();
@ -56,8 +57,39 @@ class FooterActionButton {
case WorkOrderNextStepEnum.markedAsFixed: case WorkOrderNextStepEnum.markedAsFixed:
break; break;
// TODO: Handle this case. // 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: 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( return footerContainer(
child: AppFilledButton( child: AppFilledButton(
label: context.translation.close, label: context.translation.close,

@ -68,7 +68,7 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
//backgroundColor: const Color(0xfff8f9fb), //backgroundColor: const Color(0xfff8f9fb),
body: Consumer<ServiceRequestDetailProvider>(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) { body: Consumer<ServiceRequestDetailProvider>(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) {
activities = requestDetailProvider.currentWorkOrder!.data!.activities; 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)) { if (activities.isNotEmpty && (activities.last.activityStatus!.value == 14 || activities.last.activityStatus!.value == 19)) {
disableNewActivity = true; disableNewActivity = true;
} else { } else {
@ -165,7 +165,7 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
// backgroundColor: AppColor.getHistoryLogStatusColorByName(activity.activityStatus!.name!), // backgroundColor: AppColor.getHistoryLogStatusColorByName(activity.activityStatus!.name!),
backgroundColor: AppColor.primary10, 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) if (userProvider.user!.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.status?.value != 5 && requestDetailProvider.currentWorkOrder?.data?.status?.value != 3)
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -225,11 +225,6 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
), ),
2.height, 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) ...[ if (activity.activitySparePart?.comment?.isNotEmpty ?? false) ...[
const Divider().defaultStyle(context), const Divider().defaultStyle(context),
2.height, 2.height,
@ -245,11 +240,26 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
], ],
], ],
).toShadowContainer(context, padding: 12, showShadow: false).onPress(() { ).toShadowContainer(context, padding: 12, showShadow: false).onPress(() {
//TODO write onview detail method.. // if(requestDetailProvider.currentWorkOrder?.data?.status?.id ==3498){
// Navigator.push( // requestDetailProvider.sparePartHelperModel = SparePartHelperModel(
// context, // id: activity.id,
// MaterialPageRoute(builder: (context) => WorkOrderDetailsPage(workOrder: activity, serviceRequest: ServiceRequest())), // 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<ActivitiesListView> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
//TODO will be here when fixed from backend.. //TODO will be here when fixed from backend..
StatusLabel( Row(
label: activity.activityStatus?.name, children: [
textColor: AppColor.white10, StatusLabel(
// textColor: AppColor.getHistoryLogStatusTextColorByName(activity.activityStatus!.name!), label: activity.activityStatus?.name,
// backgroundColor: AppColor.getHistoryLogStatusColorByName(activity.activityStatus!.name!), textColor: AppColor.white10,
backgroundColor: AppColor.primary10, // 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) if (userProvider.user!.type == UsersTypes.engineer && requestDetailProvider.currentWorkOrder?.data?.status?.value != 5 && requestDetailProvider.currentWorkOrder?.data?.status?.value != 3)
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -308,7 +331,7 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
), ),
2.height, 2.height,
if (activity.activityMaintenance?.assignedEmployee != null && activity.activityMaintenance!.assistantEmployees!.isNotEmpty) ...[ if (activity.activityMaintenance?.assistantEmployees != null && activity.activityMaintenance!.assistantEmployees!.isNotEmpty) ...[
Text( Text(
'${context.translation.assistantEmployee}: ${activity.activityMaintenance?.assistantEmployees?.first.user?.userName}', '${context.translation.assistantEmployee}: ${activity.activityMaintenance?.assistantEmployees?.first.user?.userName}',
style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
@ -329,8 +352,21 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120), 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 { void onEditMaintenanceRequestPress({required BuildContext context, required ServiceRequestDetailProvider requestDetailProvider, required Activities activity}) async {
@ -391,7 +427,7 @@ class _ActivitiesListViewState extends State<ActivitiesListView> {
} }
Navigator.of(context).push(MaterialPageRoute( 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();
}
}

@ -27,27 +27,41 @@ class AssetDetailCard extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
StatusLabel( Row(
label: requestDetailProvider.engineerUpdateWorkOrderHelperModel?.equipmentStatus?.name, children: [
id: requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.id ?? 0, StatusLabel(
radius: 4, label: requestDetailProvider.engineerUpdateWorkOrderHelperModel?.equipmentStatus?.name,
textColor: AppColor.white10, id: requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.id ?? 0,
backgroundColor: AppColor.getEquipmentStatusColor(context, 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{ //hide if status is closed or complete .
requestDetailProvider.refreshTimer = false; if (!requestDetailProvider.isReadOnlyRequest)
await Navigator.push( "edit_icon".toSvgAsset(height: 21, width: 21).onPress(() async {
context, requestDetailProvider.refreshTimer = false;
MaterialPageRoute( await Navigator.push(
builder: (context) => VerifyAssetDetails( context,
isEdit: true, MaterialPageRoute(
))); builder: (context) => VerifyAssetDetails(
requestDetailProvider.refreshTimer = true; isEdit: true,
}), )));
requestDetailProvider.refreshTimer = true;
}),
]), ]),
6.height, 6.height,
Text( Text(
context.translation.assetSituation, "Work Order Details",
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
), ),
Text( Text(

@ -704,7 +704,7 @@ class ServiceRequestBottomSheet {
); );
Navigator.pushReplacement( Navigator.pushReplacement(
context, context,
MaterialPageRoute(builder: (context) => const MaintenanceRequestForm()), MaterialPageRoute(builder: (context) => MaintenanceRequestForm()),
); );
break; break;
} }
@ -837,14 +837,14 @@ class ServiceRequestBottomSheet {
} }
static bool validateAssetSituation(ServiceRequestDetailProvider requestDetailProvider) { static bool validateAssetSituation(ServiceRequestDetailProvider requestDetailProvider) {
if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus != null) { // if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus != null) {
if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.value == 1 || requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.value == 2) { // if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.value == 1 || requestDetailProvider.engineerUpdateWorkOrderHelperModel!.equipmentStatus!.value == 2) {
if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.returnToService == null) { // if (requestDetailProvider.engineerUpdateWorkOrderHelperModel!.returnToService == null) {
Fluttertoast.showToast(msg: "Return to service is required ", toastLength: Toast.LENGTH_LONG); // Fluttertoast.showToast(msg: "Return to service is required ", toastLength: Toast.LENGTH_LONG);
return false; // return false;
} // }
} // }
} // }
return true; return true;
} }

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/controllers/api_routes/urls.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/initial_visit_card.dart';
import 'package:test_sa/service_request_latest/views/components/timer_widget.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/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/loaders/no_data_found.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart';
import 'package:test_sa/views/widgets/sound/sound_player.dart'; import 'package:test_sa/views/widgets/sound/sound_player.dart';
class ServiceRequestDetailView extends StatelessWidget { class ServiceRequestDetailView extends StatefulWidget {
const ServiceRequestDetailView({Key? key}) : super(key: key); ServiceRequestDetailView({Key? key}) : super(key: key);
@override
State<ServiceRequestDetailView> createState() => _ServiceRequestDetailViewState();
}
class _ServiceRequestDetailViewState extends State<ServiceRequestDetailView> {
List<File> _workOrderAttachments = [];
@override
void initState() {
ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -45,31 +62,34 @@ class ServiceRequestDetailView extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
workOrderDetailCard(context, requestProvider.currentWorkOrder!.data!, _userProvider), workOrderDetailCard(context, requestProvider.currentWorkOrder!.data!, _userProvider, requestProvider),
initialVisitCard(requestDetailProvider: requestProvider, userProvider: _userProvider), initialVisitCard(requestDetailProvider: requestProvider, userProvider: _userProvider),
assetDetailCard(requestDetailProvider: requestProvider, userProvider: _userProvider), assetDetailCard(requestDetailProvider: requestProvider, userProvider: _userProvider),
12.height,
contactInfoCard(context, requestProvider.currentWorkOrder!.data!),
20.height, 20.height,
], ],
), ),
).expanded, ).expanded,
FooterActionButton.requestDetailsFooterWidget( FooterActionButton.requestDetailsFooterWidget(
workOrderNextStepStatus: requestProvider.currentWorkOrder!.data!.nextStep!.workOrderNextStepEnum!, workOrderNextStepStatus: requestProvider.currentWorkOrder!.data!.nextStep!.workOrderNextStepEnum!,
// workOrderNextStepStatus: WorkOrderNextStepEnum.eNeedVisit, status: requestProvider.currentWorkOrder?.data?.status,
isEmpIsAssigned: requestProvider.currentWorkOrder!.data!.assignedEmployee != null, isEmpIsAssigned: requestProvider.currentWorkOrder!.data!.assignedEmployee != null,
activities: requestProvider.currentWorkOrder!.data?.activities ?? [], activities: requestProvider.currentWorkOrder!.data?.activities ?? [],
userProvider: _userProvider, userProvider: _userProvider,
context: context), context: context),
], ],
), ),
if (requestProvider.timer != null && requestProvider.timer!.isActive) ...[ //no need to show timer as discussed with backend
const TimerWidget(), // 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( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -100,6 +120,15 @@ class ServiceRequestDetailView extends StatelessWidget {
textColor: AppColor.getHistoryLogStatusTextColorByName(workOrder.status!.name!), textColor: AppColor.getHistoryLogStatusTextColorByName(workOrder.status!.name!),
backgroundColor: AppColor.getHistoryLogStatusColorByName(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, 1.width.expanded,
Column( Column(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
@ -191,9 +220,18 @@ class ServiceRequestDetailView extends StatelessWidget {
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
), ),
Text( Text(
'Date/Time: ${workOrder.requestedDate!.toString().toServiceRequestDetailsFormat}', 'Requested Date: ${workOrder.requestedDate!.toString().toServiceRequestDetailsFormat}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral120), 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), const Divider().defaultStyle(context),
//... call response details starts here.... //... call response details starts here....
@ -215,13 +253,40 @@ class ServiceRequestDetailView extends StatelessWidget {
'${context.translation.activityStatus}: ${workOrder.lastActivityStatus?.name ?? "-"}', '${context.translation.activityStatus}: ${workOrder.lastActivityStatus?.name ?? "-"}',
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), 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, 8.height,
if ((workOrder.comments ?? "").isNotEmpty) ...[ if ((workOrder.comments ?? "").isNotEmpty) ...[
const Divider().defaultStyle(context), const Divider().defaultStyle(context),
8.height, 8.height,
Text( Text(
"Call Comment", context.translation.callComments,
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
), ),
8.height, 8.height,
@ -230,11 +295,23 @@ class ServiceRequestDetailView extends StatelessWidget {
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120), style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral120),
), ),
], ],
if (workOrder.workOrderAttachments.isNotEmpty ?? false) ...[
if (!requestProvider.isReadOnlyRequest) ...[
8.height, 8.height,
const Divider().defaultStyle(context), 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) ...[ if (workOrder.voiceNote?.isNotEmpty ?? false) ...[
const Divider().defaultStyle(context), const Divider().defaultStyle(context),
16.height, 16.height,
@ -308,6 +385,55 @@ class ServiceRequestDetailView extends StatelessWidget {
).toShadowContainer(context, padding: 0); ).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}) { Widget assetRetiredButton({required BuildContext context}) {
return Padding( return Padding(
padding: EdgeInsets.symmetric(horizontal: 16.toScreenHeight, vertical: 12.toScreenWidth), 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}) { 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!; WorkOrderData currentWorkOrderData = requestDetailProvider.currentWorkOrder!.data!;
requestDetailProvider.engineerUpdateWorkOrderHelperModel = EngineerUpdateWorkOrderHelperModel( requestDetailProvider.engineerUpdateWorkOrderHelperModel = EngineerUpdateWorkOrderHelperModel(
workOrderId: currentWorkOrderData.requestId, workOrderId: currentWorkOrderData.requestId,

@ -1,7 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.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/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_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.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/new_views/common_widgets/single_item_drop_down_menu.dart';
import 'package:test_sa/providers/loading_list_notifier.dart'; import 'package:test_sa/providers/loading_list_notifier.dart';
import 'package:test_sa/providers/service_request_providers/equipment_status_provider.dart'; import 'package:test_sa/providers/service_request_providers/equipment_status_provider.dart';
@ -75,6 +75,7 @@ class _VerifyAssetDetailsState extends State<VerifyAssetDetails> with TickerProv
solution: currentWorkOrderData.faultDescription?.workPerformed, solution: currentWorkOrderData.faultDescription?.workPerformed,
returnToService: currentWorkOrderData.returnToService, returnToService: currentWorkOrderData.returnToService,
serviceType: currentWorkOrderData.serviceType, serviceType: currentWorkOrderData.serviceType,
callResponse: currentWorkOrderData.callResponse,
); );
if (currentWorkOrderData.assetLoan != null) { if (currentWorkOrderData.assetLoan != null) {
loanAvailabilityAsset = Asset( loanAvailabilityAsset = Asset(
@ -215,12 +216,27 @@ class _VerifyAssetDetailsState extends State<VerifyAssetDetails> with TickerProv
} }
}, },
), ),
12.height, if (requestDetailProvider.engineerUpdateWorkOrderHelperModel?.solution != null) ...[
context.translation.solutions.heading6(context).custom(color: AppColor.neutral50), 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, 8.height,
requestDetailProvider.engineerUpdateWorkOrderHelperModel?.solution != null AppTextFormField(
? requestDetailProvider.engineerUpdateWorkOrderHelperModel!.solution!.bodyText2(context).custom(color: AppColor.neutral120) labelText: context.translation.callResponse,
: const SizedBox(), 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), ).toShadowContainer(context).paddingAll(16),
).expanded, ).expanded,

@ -39,6 +39,11 @@ class _AssistantEmployeeCardState extends State<AssistantEmployeeCard> {
Future<void> getInitialData() async { Future<void> getInitialData() async {
final user = Provider.of<UserProvider>(context, listen: false).user!; final user = Provider.of<UserProvider>(context, listen: false).user!;
ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false); ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
if( requestDetailProvider.isReadOnlyRequest){
isExpanded = true;
setState(() {
});
}
isCurrentUserIsAssistantEmp = (user.userID != requestDetailProvider.currentWorkOrder?.data?.assignedEmployee?.userId); isCurrentUserIsAssistantEmp = (user.userID != requestDetailProvider.currentWorkOrder?.data?.assignedEmployee?.userId);
// if (isCurrentUserIsAssistantEmp) { // if (isCurrentUserIsAssistantEmp) {
@ -122,7 +127,7 @@ class _AssistantEmployeeCardState extends State<AssistantEmployeeCard> {
requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
ServiceRequestUtils.calculateAndAssignWorkingHours( ServiceRequestUtils.calculateAndAssignWorkingHours(
startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate,
endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate,
workingHoursController: _workingHoursController, workingHoursController: _workingHoursController,
updateModel: (hours){ updateModel: (hours){
requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours=hours; requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours=hours;

@ -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<PreventiveVisitSuppliers>? models;
// //
// // const AssistantEmployeeList({Key? key, this.models = const <PreventiveVisitSuppliers>[]}) : super(key: key);
// //
// // @override
// // State<AssistantEmployeeList> createState() => _AssistantEmployeeListState();
// // }
// //
// // class _AssistantEmployeeListState extends State<AssistantEmployeeList> {
// // 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<SupplierDetails, VendorProvider>(
// // 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<SuppPersons, NullableLoadingProvider>(
// // 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<ActivityMaintenanceAssistantEmployees>? models;
//
// const AssistantEmployeeList({Key? key, this.models = const <ActivityMaintenanceAssistantEmployees>[]}) : super(key: key);
//
// @override
// State<AssistantEmployeeList> createState() => _AssistantEmployeeListState();
// }
//
// class _AssistantEmployeeListState extends State<AssistantEmployeeList> {
// 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<PpmProvider>(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<AssistantEmployeeItem> createState() => _AssistantEmployeeItemState();
// }
//
// class _AssistantEmployeeItemState extends State<AssistantEmployeeItem> {
// 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<void> getInitialData() async {
// final user = Provider.of<UserProvider>(context, listen: false).user!;
// ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(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<ServiceRequestDetailProvider>(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;
// // }
// // }
// }
//

@ -42,198 +42,198 @@ class _ExternalMaintenanceRequestState extends State<ExternalMaintenanceRequest>
ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false); ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
_workingHoursController.text = _workingHoursController.text =
requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour != null ? requestDetailProvider.activityMaintenanceHelperModel!.supplierWorkingHour.toString() : ''; requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour != null ? requestDetailProvider.activityMaintenanceHelperModel!.supplierWorkingHour.toString() : '';
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer<ServiceRequestDetailProvider>(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) { return Consumer<ServiceRequestDetailProvider>(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) {
return Column( return IgnorePointer(
children: [ ignoring: requestDetailProvider.isReadOnlyRequest,
Form( child: Column(
key: _formKey, children: [
child: Column( Form(
mainAxisSize: MainAxisSize.min, key: _formKey,
children: [ child: Column(
SingleItemDropDownMenu<SupplierDetails, VendorProvider>( mainAxisSize: MainAxisSize.min,
context: context, children: [
title: context.translation.supplier, SingleItemDropDownMenu<SupplierDetails, VendorProvider>(
backgroundColor: AppColor.neutral100, context: context,
initialValue: requestDetailProvider.activityMaintenanceHelperModel?.supplier, title: context.translation.supplier,
showAsBottomSheet: true, backgroundColor: AppColor.neutral100,
onSelect: (supplier) { initialValue: requestDetailProvider.activityMaintenanceHelperModel?.supplier,
if (supplier != null) { showAsBottomSheet: true,
requestDetailProvider.activityMaintenanceHelperModel?.supplier = supplier; onSelect: (supplier) {
// _subWorkOrders.supplier = supplier; if (supplier != null) {
// log(_subWorkOrders.supplier?.suppPersons?.map((e) => e.personName)?.toString()); requestDetailProvider.activityMaintenanceHelperModel?.supplier = supplier;
setState(() {}); // _subWorkOrders.supplier = supplier;
} // log(_subWorkOrders.supplier?.suppPersons?.map((e) => e.personName)?.toString());
}, setState(() {});
), }
8.height, },
Row( ),
children: [ 8.height,
SingleItemDropDownMenu<SuppPersons, NullableLoadingProvider>( Row(
context: context, children: [
backgroundColor: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null ? AppColor.neutral40 : AppColor.neutral100, SingleItemDropDownMenu<SuppPersons, NullableLoadingProvider>(
title: context.translation.supplierEngineer, context: context,
enabled: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons?.isNotEmpty ?? false, backgroundColor: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null ? AppColor.neutral40 : AppColor.neutral100,
staticData: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons, title: context.translation.supplierEngineer,
showAsBottomSheet: true, enabled: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons?.isNotEmpty ?? false,
initialValue: requestDetailProvider.activityMaintenanceHelperModel?.supEngineer == null staticData: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons,
? null showAsBottomSheet: true,
: SuppPersons.fromJson(requestDetailProvider.activityMaintenanceHelperModel?.supEngineer?.toJson()), initialValue: requestDetailProvider.activityMaintenanceHelperModel?.supEngineer == null
onSelect: (suppPerson) { ? null
print(suppPerson?.toJson()); : SuppPersons.fromJson(requestDetailProvider.activityMaintenanceHelperModel?.supEngineer?.toJson()),
if (suppPerson != null) { onSelect: (suppPerson) {
requestDetailProvider.activityMaintenanceHelperModel?.supEngineer = SuppEngineerWorkOrders.fromJson(suppPerson.toJson()); print(suppPerson?.toJson());
requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); if (suppPerson != null) {
// engineer = SuppEngineerWorkOrders( requestDetailProvider.activityMaintenanceHelperModel?.supEngineer = SuppEngineerWorkOrders.fromJson(suppPerson.toJson());
// 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;
requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel); requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
_workingHoursController.clear(); // engineer = SuppEngineerWorkOrders(
ServiceRequestUtils.calculateAndAssignWorkingHours( // id: suppPerson?.supplierId,
startTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime, // supplierContactId: suppPerson?.id,
endTime: requestDetailProvider.activityMaintenanceHelperModel!.endTime, // personName: suppPerson?.personName,
workingHoursController: _workingHoursController, // contact: suppPerson?.contact,
updateModel: (hours) { // externalEngCode: suppPerson?.externalEngCode,
requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour = hours; // email: suppPerson?.email,
}, // );
); setState(() {});
} }
}); },
}, ).expanded,
).expanded, 8.width,
8.width, Container(
ADatePicker( height: 56.toScreenHeight,
label: context.translation.endTime, width: 60.toScreenWidth,
hideShadow: true, decoration: BoxDecoration(
backgroundColor: AppColor.neutral100, color: requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null ? AppColor.neutral40 : AppColor.neutral100,
date: requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime, borderRadius: BorderRadius.circular(10),
formatDateWithTime: true, boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
onDatePicker: (selectedDate) { ),
showTimePicker( child: Icon(
context: context, Icons.add,
initialTime: TimeOfDay.now(), color: context.isDark ? null : AppColor.neutral60,
).then((selectedTime) { ),
// Handle the selected date and time here. ).onPress(requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppliername == null
if (selectedTime != null) { ? null
DateTime selectedDateTime = DateTime( : () async {
selectedDate.year, SuppEngineerWorkOrders suppEngineer = (await showModalBottomSheet(
selectedDate.month, context: context,
selectedDate.day, useSafeArea: true,
selectedTime.hour, isScrollControlled: true,
selectedTime.minute, backgroundColor: Colors.transparent,
); builder: (context) => AddSupplierEngineerBottomSheet(requestDetailProvider.activityMaintenanceHelperModel!.supplier!.id!.toInt()),
if (requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime != null && )) as SuppEngineerWorkOrders;
selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime!)) { requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons ??= [];
"End Date time must be greater then start date".showToast; requestDetailProvider.activityMaintenanceHelperModel?.supplier?.suppPersons?.add(SuppPersons.fromJson(suppEngineer.toJson()));
return; 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( ).expanded,
startTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime, 8.width,
endTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierEndTime, ADatePicker(
workingHoursController: _workingHoursController, label: context.translation.endTime,
updateModel: (hours) { hideShadow: true,
requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour = hours; backgroundColor: AppColor.neutral100,
}, date: requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime,
); formatDateWithTime: true,
} onDatePicker: (selectedDate) {
}); showTimePicker(
}, context: context,
).expanded, initialTime: TimeOfDay.now(),
], ).then((selectedTime) {
), // Handle the selected date and time here.
8.height, if (selectedTime != null) {
AppTextFormField( DateTime selectedDateTime = DateTime(
labelText: context.translation.workingHours, selectedDate.year,
backgroundColor: AppColor.neutral80, selectedDate.month,
controller: _workingHoursController, selectedDate.day,
suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16), selectedTime.hour,
initialValue: selectedTime.minute,
requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour != null ? requestDetailProvider.activityMaintenanceHelperModel?.supplierWorkingHour.toString() : '', );
textAlign: TextAlign.center, if (requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime != null &&
labelStyle: AppTextStyles.textFieldLabelStyle, selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime!)) {
enable: false, "End Date time must be greater then start date".showToast;
showShadow: false, return;
style: Theme.of(context).textTheme.titleMedium, }
), requestDetailProvider.activityMaintenanceHelperModel?.supplierEndTime = selectedDateTime;
8.height, requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
], ServiceRequestUtils.calculateAndAssignWorkingHours(
), startTime: requestDetailProvider.activityMaintenanceHelperModel!.supplierStartTime,
).toShadowContainer(context).paddingOnly(start: 16, end: 16, top: 12), 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),
],
),
); );
}); });
} }
} }

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_repair_location_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_repair_location_provider.dart';
@ -32,6 +34,7 @@ class _InternalMaintenanceRequestState extends State<InternalMaintenanceRequest>
final TextEditingController _travellingHoursController = TextEditingController(); final TextEditingController _travellingHoursController = TextEditingController();
Lookup statusLookup = Lookup.fromJson({"id": 5619, "name": "New", "value": 1}); Lookup statusLookup = Lookup.fromJson({"id": 5619, "name": "New", "value": 1});
@override @override
void initState() { void initState() {
_requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false); _requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
@ -53,8 +56,6 @@ class _InternalMaintenanceRequestState extends State<InternalMaintenanceRequest>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer<ServiceRequestDetailProvider>(builder: (context, requestDetailProvider, child) { return Consumer<ServiceRequestDetailProvider>(builder: (context, requestDetailProvider, child) {
double totalWorkingHours = _requestDetailProvider?.activityMaintenanceHelperModel?.activityMaintenanceTimers double totalWorkingHours = _requestDetailProvider?.activityMaintenanceHelperModel?.activityMaintenanceTimers
?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endTime!).difference(DateTime.parse(item.startTime!)).inSeconds) ?? ?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endTime!).difference(DateTime.parse(item.startTime!)).inSeconds) ??
0; 0;
@ -64,228 +65,231 @@ class _InternalMaintenanceRequestState extends State<InternalMaintenanceRequest>
: requestDetailProvider.activityMaintenanceHelperModel?.id == requestDetailProvider.lastVisitedRequestActivityId; : requestDetailProvider.activityMaintenanceHelperModel?.id == requestDetailProvider.lastVisitedRequestActivityId;
return SingleChildScrollView( return SingleChildScrollView(
child: Column( child: IgnorePointer(
children: [ ignoring: _requestDetailProvider!.isReadOnlyRequest,
Form( child: Column(
key: _formKey, children: [
child: Column( Form(
crossAxisAlignment: CrossAxisAlignment.stretch, key: _formKey,
children: [ child: Column(
// SingleItemDropDownMenu<Lookup, ActivityStatusProvider>( crossAxisAlignment: CrossAxisAlignment.stretch,
// context: context, children: [
// height: 56.toScreenHeight, // SingleItemDropDownMenu<Lookup, ActivityStatusProvider>(
// title: context.translation.activityStatus, // context: context,
// showShadow: false, // height: 56.toScreenHeight,
// backgroundColor: AppColor.neutral100, // title: context.translation.activityStatus,
// initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus, // showShadow: false,
// onSelect: (status) { // backgroundColor: AppColor.neutral100,
// print('status i got is ${status?.toJson()}'); // initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
// requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status; // onSelect: (status) {
// }, // print('status i got is ${status?.toJson()}');
// ), // requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
// 8.height, // },
SingleItemDropDownMenu<Lookup, LastSituationProvider>( // ),
context: context, // 8.height,
height: 56.toScreenHeight, SingleItemDropDownMenu<Lookup, LastSituationProvider>(
title: context.translation.activityStatus, context: context,
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, height: 56.toScreenHeight,
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), title: context.translation.activityStatus,
alignment: Alignment.centerLeft, showShadow: false,
decoration: BoxDecoration( backgroundColor: AppColor.neutral100,
color: context.isDark ? AppColor.neutral40 : AppColor.background(context), showAsBottomSheet: true,
borderRadius: BorderRadius.circular(10), initialValue: requestDetailProvider.activityMaintenanceHelperModel?.activityStatus,
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], onSelect: (status) {
), if (status != null) {
child: Column( requestDetailProvider.activityMaintenanceHelperModel?.activityStatus = status;
crossAxisAlignment: CrossAxisAlignment.start, setState(() {});
mainAxisAlignment: MainAxisAlignment.center, }
children: [ },
Text( ),
"Total Working Time", 8.height,
style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), AppTimer(
), label: context.translation.timer,
Text( timer: requestDetailProvider.activityMaintenanceHelperModel?.activityMaintenanceTimerModel,
" ${ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round())}", enabled: enableTimer,
style: Theme.of(context).textTheme.bodyMedium, 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, 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( ).toShadowContainer(context).paddingOnly(start: 13, end: 14, top: 12),
// labelText: context.translation.workingHours, const AssistantEmployeeCard().toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16)).paddingOnly(start: 13, end: 14, top: 12),
// backgroundColor: AppColor.neutral80, 100.height,
// 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,
],
), ),
); );
}); });

@ -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'; import 'package:test_sa/service_request_latest/views/forms/maintenance_request/components/internal_request.dart';
class MaintenanceRequestForm extends StatefulWidget { class MaintenanceRequestForm extends StatefulWidget {
const MaintenanceRequestForm({Key? key}) : super(key: key); MaintenanceRequestForm({Key? key}) : super(key: key);
@override @override
_MaintenanceRequestFormState createState() => _MaintenanceRequestFormState(); _MaintenanceRequestFormState createState() => _MaintenanceRequestFormState();
@ -47,9 +47,16 @@ class _MaintenanceRequestFormState extends State<MaintenanceRequestForm> with Si
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer<ServiceRequestDetailProvider>(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) { return Consumer<ServiceRequestDetailProvider>(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) {
bool isUpdate = requestDetailProvider.activityMaintenanceHelperModel?.id != 0; bool isUpdate = requestDetailProvider.activityMaintenanceHelperModel?.id != 0;
return Scaffold( return Scaffold(
backgroundColor: AppColor.neutral110, backgroundColor: AppColor.neutral110,
appBar: const DefaultAppBar(title: "CM Activity"), appBar: DefaultAppBar(
title: "CM Activity",
onWillPopScope: requestDetailProvider.isReadOnlyRequest
? null
: () {
save(requestDetailProvider);
},
),
body: Stack( body: Stack(
children: [ children: [
DefaultTabController( DefaultTabController(
@ -92,53 +99,55 @@ class _MaintenanceRequestFormState extends State<MaintenanceRequestForm> with Si
], ],
), ),
), ),
FooterActionButton.footerContainer( if (!requestDetailProvider.isReadOnlyRequest)
child: AppFilledButton( FooterActionButton.footerContainer(
label: requestDetailProvider.activityMaintenanceHelperModel?.id != 0 ? context.translation.update : context.translation.addActivity, // Use the dynamic label child: AppFilledButton(
buttonColor: AppColor.primary10, label: requestDetailProvider.activityMaintenanceHelperModel?.id != 0 ? context.translation.update : context.translation.addActivity, // Use the dynamic label
onPressed: () async { buttonColor: AppColor.primary10,
//TODO add this as dropdown not added in design yet Bhaa need to confirm with hussain then. onPressed: () async {
// requestDetailProvider.activityMaintenanceHelperModel?.lastSituationId = 282; save(requestDetailProvider);
},
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
},
), ),
),
], ],
), ),
); ).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}) { bool validate({required ActivityMaintenanceHelperModel model}) {
if (model.activityStatus == null) { if (model.activityStatus == null) {
Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.activityStatus}"); Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.activityStatus}");

@ -4,6 +4,7 @@ import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.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/controllers/providers/api/parts_provider.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.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/extensions/widget_extensions.dart';
import 'package:test_sa/models/helper_data_models/spare_part/activity_spare_part_model.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/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/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_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/single_item_drop_down_menu.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/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/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/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 '../../../../../../models/service_request/spare_parts.dart';
import '../../../../../../new_views/common_widgets/app_text_form_field.dart'; import '../../../../../../new_views/common_widgets/app_text_form_field.dart';
@ -80,7 +83,7 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
_isLoading = true; _isLoading = true;
_files = _requestDetailProvider?.sparePartHelperModel?.sparePartAttachments?.map((e) => MultiFilesPickerModel(e.id!, File(e.name!))).toList() ?? []; _files = _requestDetailProvider?.sparePartHelperModel?.sparePartAttachments?.map((e) => MultiFilesPickerModel(e.id!, File(e.name!))).toList() ?? [];
setState(() {}); setState(() {});
_spareParts = await _partsProvider!.getPartsList(assetId: _requestDetailProvider?.currentWorkOrder?.data?.asset?.id); _spareParts = await _partsProvider!.getPartsListByDisplayName(assetId: _requestDetailProvider?.currentWorkOrder?.data?.asset?.id);
_isLoading = false; _isLoading = false;
setState(() {}); setState(() {});
@ -119,6 +122,7 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
key: _scaffoldKey, key: _scaffoldKey,
appBar: DefaultAppBar(title: context.translation.sparePartRequest), appBar: DefaultAppBar(title: context.translation.sparePartRequest),
body: Consumer<ServiceRequestDetailProvider>(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) { body: Consumer<ServiceRequestDetailProvider>(builder: (context, ServiceRequestDetailProvider requestDetailProvider, child) {
print('data i got is ${requestDetailProvider.sparePartHelperModel?.sparePart?.toJson()}');
return SafeArea( return SafeArea(
child: Form( child: Form(
key: _formKey, key: _formKey,
@ -148,14 +152,14 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
12.height, 12.height,
SingleItemDropDownMenu<SparePart, NullableLoadingProvider>( SingleItemDropDownMenu<SparePart, NullableLoadingProvider>(
context: context, context: context,
title: context.translation.partNo, title: context.translation.part,
staticData: _spareParts, staticData: _spareParts,
showShadow: false, showShadow: false,
showAsBottomSheet: true, showAsBottomSheet: true,
loading: _isLoading, loading: _isLoading,
initialValue: requestDetailProvider.sparePartHelperModel?.sparePart, initialValue: requestDetailProvider.sparePartHelperModel?.sparePart,
backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90, backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90,
onSelect: (part) { onSelect: (part) async {
if (part != null) { if (part != null) {
requestDetailProvider.sparePartHelperModel?.sparePart = part; requestDetailProvider.sparePartHelperModel?.sparePart = part;
_oracleNoController.text = part.oracleCode ?? ''; _oracleNoController.text = part.oracleCode ?? '';
@ -163,6 +167,36 @@ class _SparePartRequestState extends State<SparePartRequest> 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, 12.height,
AppTextFormField( AppTextFormField(
controller: _partQtyController, controller: _partQtyController,
@ -245,7 +279,7 @@ class _SparePartRequestState extends State<SparePartRequest> with TickerProvider
controller: _descriptionController, controller: _descriptionController,
showSpeechToText: true, showSpeechToText: true,
backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90, backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90,
labelText: context.translation.description, labelText: "Engineer Comment",
alignLabelWithHint: true, alignLabelWithHint: true,
showWithoutDecoration: true, showWithoutDecoration: true,
textInputType: TextInputType.multiline, textInputType: TextInputType.multiline,
@ -309,4 +343,58 @@ class _SparePartRequestState extends State<SparePartRequest> 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<ServiceRequestDetailProvider>(
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);
}
} }

@ -128,10 +128,10 @@ class _ServiceRequestDetailMainState extends State<ServiceRequestDetailMain> {
), ),
), ),
12.height, 12.height,
const TabBarView( TabBarView(
children: [ children: [
ServiceRequestDetailView(), ServiceRequestDetailView(),
HistoryLogView(), const HistoryLogView(),
], ],
).expanded, ).expanded,
], ],

@ -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<CreateAssetTransferRequest> createState() => _CreateAssetTransferRequestState();
}
class _CreateAssetTransferRequestState extends State<CreateAssetTransferRequest> {
late AssetTransferProvider _deviceTransferProvider;
final TextEditingController _requestedQuantityController = TextEditingController();
final AssetTransfer _transferModel = AssetTransfer(id: 0);
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final TextEditingController _receiverNameController = TextEditingController(), _commentsController = TextEditingController();
final Asset _assetDestination = Asset();
Asset? _pickedAsset;
final List<File> _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<AssetTransferAttachment> 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<PpmServiceProvider>(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<AssetTransferProvider>(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<Site, SiteProvider>(
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<Building, NullableLoadingProvider>(
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<Floor, NullableLoadingProvider>(
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<Department, NullableLoadingProvider>(
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<void> 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<PpmServiceProvider>(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),
],
);
});
}
}

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/asset_transfer_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/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset_transfer.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/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/app_loading.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
@ -31,6 +34,7 @@ class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
AssetTransfer? _model; AssetTransfer? _model;
final bool _isLoading = false; final bool _isLoading = false;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
List<File> _attachments = [];
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@override @override
@ -41,6 +45,7 @@ class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_userProvider ??= Provider.of<UserProvider>(context); _userProvider ??= Provider.of<UserProvider>(context);
return Scaffold( return Scaffold(
appBar: DefaultAppBar(title: context.translation.deviceTransferDetails), appBar: DefaultAppBar(title: context.translation.deviceTransferDetails),
key: _scaffoldKey, key: _scaffoldKey,
@ -52,6 +57,7 @@ class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
return const ALoading(); return const ALoading();
} else { } else {
_model = snapshot.data as AssetTransfer?; _model = snapshot.data as AssetTransfer?;
_attachments = _model?.attachments?.map((e) => File(e.attachmentName ?? '')).toList() ?? [];
return Form( return Form(
key: _formKey, key: _formKey,
@ -89,6 +95,8 @@ class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
const Divider().defaultStyle(context), const Divider().defaultStyle(context),
8.height, 8.height,
_buildTextWidget(_model!.comment!), _buildTextWidget(_model!.comment!),
] ]
], ],
), ),
@ -177,6 +185,27 @@ class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
return widget.toShadowContainer(context).paddingOnly(top: 14, start: 14, end: 14); 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) { _buildTextWidget(String text) {
return text.bodyText(context); return text.bodyText(context);
} }
@ -224,6 +253,8 @@ class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
const Divider().defaultStyle(context), const Divider().defaultStyle(context),
8.height, 8.height,
_buildTextWidget(comment), _buildTextWidget(comment),
attachmentWidget(),
] ]
], ],
).toShadowContainer(context); ).toShadowContainer(context);
@ -237,4 +268,6 @@ class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
} }
} }
} }

@ -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<RequestDeviceTransfer> createState() => _RequestDeviceTransferState();
}
class _RequestDeviceTransferState extends State<RequestDeviceTransfer> {
UserProvider? _userProvider;
SettingProvider? _settingProvider;
late AssetTransferProvider _deviceTransferProvider;
final TextEditingController _requestedQuantityController = TextEditingController();
final AssetTransfer _transferModel = AssetTransfer();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
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<UserProvider>(context, listen: false);
_settingProvider = Provider.of<SettingProvider>(context, listen: false);
_deviceTransferProvider = Provider.of<AssetTransferProvider>(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<Site, SiteProvider>(
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<NurseProvider>(context, listen: false).siteId = value!.id!.toInt();
Provider.of<NurseProvider>(context, listen: false).getData();
setState(() {});
},
),
8.height,
SingleItemDropDownMenu<Building, NullableLoadingProvider>(
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<Floor, NullableLoadingProvider>(
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<Department, NullableLoadingProvider>(
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<Rooms, NullableLoadingProvider>(
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),
),
),
);
}
}

@ -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<UpdateDeviceTransfer> createState() => _UpdateDeviceTransferState();
// }
//
// class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
// 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<FormState> _formKey = GlobalKey<FormState>();
// final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
//
// List<File> _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<UserProvider>(context);
// _settingProvider = Provider.of<SettingProvider>(context);
// _deviceTransferProvider = Provider.of<AssetTransferProvider>(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<AssetTransferStatusProvider>(builder: (context, snapshot, _) {
// return SingleItemDropDownMenu<Lookup, AssetTransferStatusProvider>(
// 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:convert';
import 'dart:io'; import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/asset_transfer_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/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/widget_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.dart';
import 'package:test_sa/models/device/asset_transfer_attachment.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/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/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/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.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 '../../../extensions/text_extensions.dart';
import '../../../models/lookup.dart';
import '../../../models/ppm/ppm.dart'; import '../../../models/ppm/ppm.dart';
import '../../../new_views/app_style/app_color.dart'; import '../../../new_views/app_style/app_color.dart';
import '../../../new_views/common_widgets/app_text_form_field.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/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'; import '../../widgets/timer/app_timer.dart';
class UpdateDeviceTransfer extends StatefulWidget { class UpdateDeviceTransfer extends StatefulWidget {
@ -42,10 +375,7 @@ class UpdateDeviceTransfer extends StatefulWidget {
class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> { class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
final bool _isLoading = false; final bool _isLoading = false;
bool _validate = false;
late UserProvider _userProvider;
late SettingProvider _settingProvider;
Uint8List? _signature;
late AssetTransferProvider _deviceTransferProvider; late AssetTransferProvider _deviceTransferProvider;
final TextEditingController _requestedQuantityController = TextEditingController(); final TextEditingController _requestedQuantityController = TextEditingController();
final AssetTransfer _formModel = AssetTransfer(); final AssetTransfer _formModel = AssetTransfer();
@ -54,27 +384,7 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
List<File> _files = []; List<File> _files = [];
_update() async { _update({required int status}) 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) { if (_formModel.tbsTimer?.startAt == null) {
await Fluttertoast.showToast(msg: "Working Hours Required"); await Fluttertoast.showToast(msg: "Working Hours Required");
return false; return false;
@ -83,19 +393,38 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
await Fluttertoast.showToast(msg: "Please Stop The Timer"); await Fluttertoast.showToast(msg: "Please Stop The Timer");
return false; return false;
} }
_validate = true;
if (!(_formKey.currentState!.validate())) { if (!(_formKey.currentState!.validate())) {
setState(() {}); setState(() {});
return false; return false;
} }
_formKey.currentState!.save(); _formKey.currentState!.save();
_formModel.statusValue = status;
_formModel.isSender = widget.isSender;
if (widget.isSender) { if (widget.isSender) {
_formModel.senderAttachments = []; _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 { } else {
_formModel.receiverAttachments = []; _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 { try {
for (var file in _files) { for (var file in _files) {
String attachmentName = file.path; String attachmentName = file.path;
@ -103,17 +432,19 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
attachmentName = file.path.split("/").last; attachmentName = file.path.split("/").last;
attachmentName = "$attachmentName|${base64Encode(file.readAsBytesSync())}"; attachmentName = "$attachmentName|${base64Encode(file.readAsBytesSync())}";
} }
if (widget.isSender) { if (widget.isSender) {
_formModel.senderAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName)); _formModel.senderAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName));
_formModel.attachments = _formModel.senderAttachments;
} else { } else {
_formModel.receiverAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName)); _formModel.receiverAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName));
_formModel.attachments = _formModel.receiverAttachments;
} }
} }
} catch (error) { } catch (error) {
print(error); print(error);
} }
await _deviceTransferProvider.updateRequest(context, assetTransfer: _formModel, isSender: widget.isSender);
await _deviceTransferProvider.updateRequest(context, model: _formModel);
} }
@override @override
@ -139,20 +470,16 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context);
_deviceTransferProvider = Provider.of<AssetTransferProvider>(context, listen: false); _deviceTransferProvider = Provider.of<AssetTransferProvider>(context, listen: false);
double totalWorkingHours = widget.isSender 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.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); : (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 bool isTimerEnable = widget.isSender
? (!(_formModel.senderMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.senderMachineStatusName?.toLowerCase().contains("complete") ?? false)) ? (!(_formModel.senderMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.senderMachineStatusName?.toLowerCase().contains("complete") ?? false))
: (!(_formModel.receiverMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.receiverMachineStatusName?.toLowerCase().contains("complete") ?? false)); : (!(_formModel.receiverMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.receiverMachineStatusName?.toLowerCase().contains("complete") ?? false));
return Scaffold( return Scaffold(
appBar: DefaultAppBar(title: context.translation.updateRequest), appBar: DefaultAppBar(title: context.translation.transferAsset),
key: _scaffoldKey, key: _scaffoldKey,
body: SafeArea( body: SafeArea(
child: LoadingManager( child: LoadingManager(
@ -167,122 +494,60 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
SingleChildScrollView( SingleChildScrollView(
padding: EdgeInsets.all(12 * AppStyle.getScaleFactor(context)), padding: EdgeInsets.all(12 * AppStyle.getScaleFactor(context)),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
_buildCard(), Column(
8.height, crossAxisAlignment: CrossAxisAlignment.stretch,
AppTextFormField( children: [
initialValue: widget.isSender ? _formModel.senderTravelingHours ?? "" : _formModel.receiverTravelingHours ?? "", _timerWidget(context, totalWorkingHours, isTimerEnable),
labelText: context.translation.travelingHours, 8.height,
onChange: (text) { AppTextFormField(
widget.isSender ? _formModel.senderTravelingHours = text : _formModel.receiverTravelingHours = text; initialValue: widget.isSender ? _formModel.senderComment ?? "" : _formModel.receiverComment ?? "",
}, labelText: context.translation.technicalComment,
onSaved: (value) { labelStyle: AppTextStyles.tinyFont.copyWith(color: AppColor.neutral20),
widget.isSender ? _formModel.senderTravelingHours = value : _formModel.receiverTravelingHours = value; textInputType: TextInputType.multiline,
//_formModel?.workingHours = double.tryParse(value); backgroundColor: AppColor.neutral100,
// _formModel.travelingHours = value; showShadow: false,
}, alignLabelWithHint: true,
textInputType: TextInputType.number, onSaved: (value) {
//validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only", widget.isSender ? _formModel.senderComment = value : _formModel.receiverComment = value;
), },
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( 8.height,
crossAxisAlignment: CrossAxisAlignment.start, MultiFilesPicker(
mainAxisAlignment: MainAxisAlignment.center, label: context.translation.attachFiles,
children: [ files: _files,
Text( buttonColor: AppColor.black10,
"Total Working Time", onlyImages: false,
style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120),
),
Text(
" ${formatDuration(totalWorkingHours.round())}",
style: Theme.of(context).textTheme.bodyLarge,
),
],
), ),
), 8.height,
8.height, ],
], ).toShadowContainer(context),
AppTimer( 16.height,
label: context.translation.workingHours, AssistantEmployeeCard(
timer: _formModel.tbsTimer, isSender: widget.isSender,
enabled: isTimerEnable, formModel: _formModel,
// enabled: widget.isSender ? _formModel.senderEndDate == null : (_formModel?.receiverMachineStatusName?.toLowerCase()?.contains("close") ?? false), ).toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16)),
timerProgress: (isRunning) {
isTimerRunning = isRunning;
},
onChange: (timer) async {
_formModel.tbsTimer = timer;
return true;
},
),
8.height,
Consumer<AssetTransferStatusProvider>(builder: (context, snapshot, _) {
return SingleItemDropDownMenu<Lookup, AssetTransferStatusProvider>(
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, ).expanded,
Padding( FooterActionButton.footerContainer(
padding: const EdgeInsets.all(16.0), child: Row(
child: AppFilledButton( mainAxisAlignment: MainAxisAlignment.spaceAround,
label: context.translation.update, children: [
onPressed: _update, 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<UpdateDeviceTransfer> {
); );
} }
_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( return Column(
crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min,
children: [ children: [
context.translation.transferDetails.heading5(context), AppTimer(
8.height, label: context.translation.workingHours,
'${context.translation.assetName}: ${_formModel.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), timer: _formModel.tbsTimer,
'${context.translation.requesterName}: ${_formModel.receiverEndUserName?.cleanupWhitespace.capitalizeFirstOfEach ?? ""}'.bodyText(context), 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) { class AssistantEmployeeCard extends StatefulWidget {
int hours = seconds ~/ 3600; bool? isSender = false;
int minutes = (seconds % 3600) ~/ 60; AssetTransfer? formModel;
int remainingSeconds = seconds % 60;
String formattedDuration = ''; AssistantEmployeeCard({super.key, this.isSender, this.formModel});
if (hours > 0) {
formattedDuration += '$hours hour${hours > 1 ? 's' : ''} '; @override
} State<AssistantEmployeeCard> createState() => _AssistantEmployeeCardState();
if (minutes > 0) { }
formattedDuration += '$minutes minute${minutes > 1 ? 's' : ''} ';
} class _AssistantEmployeeCardState extends State<AssistantEmployeeCard> {
if (remainingSeconds > 0) { final TextEditingController _workingHoursController = TextEditingController(text: '');
formattedDuration += '$remainingSeconds second${remainingSeconds > 1 ? 's' : ''} '; bool isCurrentUserIsAssistantEmp = false;
bool isExpanded = false;
List<AssetTransferAssistantEmployees> employeeList = [];
AssistantEmployees selectedEmployee = AssistantEmployees();
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
getInitialData();
});
super.initState();
}
Future<void> 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(),
],
);
} }
} }

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/gas_refill_comments.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/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/widget_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/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/app_loading.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart'; import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
@ -30,13 +35,14 @@ class GasRefillDetailsPage extends StatefulWidget {
} }
class _GasRefillDetailsPageState extends State<GasRefillDetailsPage> { class _GasRefillDetailsPageState extends State<GasRefillDetailsPage> {
GasRefillModel _model = GasRefillModel(gazRefillDetails: []); GasRefillModel _model = GasRefillModel(gasRefillDetails: []);
late UserProvider _userProvider; late UserProvider _userProvider;
late GasRefillProvider gasRefillProvider; late GasRefillProvider gasRefillProvider;
final bool _isLoading = false; final bool _isLoading = false;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
List<File> _attachments = [];
@override @override
void initState() { void initState() {
@ -61,6 +67,8 @@ class _GasRefillDetailsPageState extends State<GasRefillDetailsPage> {
return const ALoading(); return const ALoading();
} else if (snap.hasData) { } else if (snap.hasData) {
_model = snap.data as GasRefillModel; _model = snap.data as GasRefillModel;
_attachments = _model.gasRefillAttachments?.map((e) => File(e.attachmentName ?? '')).toList() ?? [];
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -68,6 +76,14 @@ class _GasRefillDetailsPageState extends State<GasRefillDetailsPage> {
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
child: informationCard(_model), child: informationCard(_model),
).expanded, ).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<GasRefillDetailsPage> {
context.translation.gasRefillRequest.heading5(context), context.translation.gasRefillRequest.heading5(context),
8.height, 8.height,
'${context.translation.gasRequest}: ${gasRefillModel.gazRefillDetails![0].gasType?.name}'.bodyText(context), '${context.translation.gasRequest}: ${gasRefillModel.gasRefillDetails![0].gasType?.name}'.bodyText(context),
'${context.translation.cylinderType}: ${gasRefillModel.gazRefillDetails![0].cylinderType?.name}'.bodyText(context), '${context.translation.cylinderType}: ${gasRefillModel.gasRefillDetails![0].cylinderType?.name}'.bodyText(context),
'${context.translation.cylinderSize}: ${gasRefillModel.gazRefillDetails![0].cylinderSize?.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.site}: ${gasRefillModel.site?.name?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context),
'${context.translation.department}: ${gasRefillModel.department?.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... //TODO need to confirm where to display this new data...
infoText(label:context.translation.gasRequest ,value:gasRefillModel.extensionNo ), infoText(label: context.translation.gasRequest, value: gasRefillModel.extensionNo),
infoText(label:context.translation.employeeId ,value:gasRefillModel.employeeId ), infoText(label: context.translation.employeeId, value: gasRefillModel.employeeId),
infoText(label:context.translation.name ,value:gasRefillModel.name ), infoText(label: context.translation.name, value: gasRefillModel.name),
infoText(label:context.translation.createdDate ,value:gasRefillModel.createdDate?.toInitialVisitCardFormat), infoText(label: context.translation.createdDate, value: gasRefillModel.createdDate?.toInitialVisitCardFormat),
const Divider().defaultStyle(context), const Divider().defaultStyle(context),
'${context.translation.requestedQuantity}: ${gasRefillModel.gazRefillDetails![0].requestedQty ?? 0}'.bodyText(context), '${context.translation.requestedQuantity}: ${gasRefillModel.gasRefillDetails![0].requestedQty ?? 0}'.bodyText(context),
'${context.translation.deliveredQuantity}: ${gasRefillModel.gazRefillDetails![0].deliverdQty ?? 0}'.bodyText(context), '${context.translation.deliveredQuantity}: ${gasRefillModel.gasRefillDetails![0].deliverdQty ?? 0}'.bodyText(context),
8.height, 8.height,
if (gasRefillModel.comment?.isNotEmpty ?? false) ...[ if (gasRefillModel.comment?.isNotEmpty ?? false) ...[
const Divider().defaultStyle(context), const Divider().defaultStyle(context),
gasRefillModel.comment!.bodyText(context), gasRefillModel.comment!.bodyText(context),
8.height, 8.height,
] ],
], if (_attachments.isNotEmpty) ...[
).expanded, const Divider().defaultStyle(context),
Column( context.translation.attachments.bodyText(context),
crossAxisAlignment: CrossAxisAlignment.end, 8.height,
children: [ MultiFilesPicker(
if (_userProvider.user!.type == UsersTypes.engineer && (gasRefillModel.status?.value ?? 0) != 2) label: context.translation.attachments,
"edit".toSvgAsset(height: 48, width: 48).onPress( files: _attachments,
() async { enabled: false,
_model.fromGasRefillModel(gasRefillModel); onlyImages: false,
// setState(() {});
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RequestGasRefill(gasRefillModel: gasRefillModel),
),
).then((value) {
if (value != null) {
_model = value;
setState(() {});
}
});
},
), ),
if (_userProvider.user!.type == UsersTypes.engineer && (gasRefillModel.status?.value ?? 0) != 2) 8.height, 12.height,
Text( ],
(widget.date ?? gasRefillModel.expectedDate)?.toServiceRequestCardFormat ?? "",
textAlign: TextAlign.end,
style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
),
], ],
).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), ).paddingOnly(top: 16, start: 16, end: 16),
/// TBD /// TBD
(_userProvider.user!.type == UsersTypes.normal_user // (_userProvider.user!.type == UsersTypes.normal_user
? Container( // ? Container(
height: 50, // height: 50,
padding: const EdgeInsets.only(left: 16, right: 16), // padding: const EdgeInsets.only(left: 16, right: 16),
alignment: Alignment.center, // alignment: Alignment.center,
width: double.infinity, // width: double.infinity,
decoration: ShapeDecoration( // decoration: ShapeDecoration(
color: context.isDark ? AppColor.neutral50 : AppColor.neutral30, // color: context.isDark ? AppColor.neutral50 : AppColor.neutral30,
shape: const RoundedRectangleBorder( // shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only( // borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(14), // bottomLeft: Radius.circular(14),
bottomRight: Radius.circular(14), // bottomRight: Radius.circular(14),
), // ),
), // ),
), // ),
child: Row( // child: Row(
children: [ // children: [
Text( // Text(
'${context.translation.commentHere}...', // '${context.translation.commentHere}...',
style: AppTextStyles.heading6.copyWith( // style: AppTextStyles.heading6.copyWith(
color: (context.isDark ? AppColor.neutral30 : AppColor.neutral50).withOpacity(.6), // color: (context.isDark ? AppColor.neutral30 : AppColor.neutral50).withOpacity(.6),
), // ),
).expanded, // ).expanded,
"comment_send".toSvgAsset(width: 24, color: context.isDark ? AppColor.primary50 : AppColor.primary70), // "comment_send".toSvgAsset(width: 24, color: context.isDark ? AppColor.primary50 : AppColor.primary70),
], // ],
), // ),
) // )
: Column( // : Column(
mainAxisSize: MainAxisSize.min, // mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
children: [ // children: [
const Divider().defaultStyle(context), // const Divider().defaultStyle(context),
8.height, // 8.height,
Row( // Row(
mainAxisSize: MainAxisSize.min, // mainAxisSize: MainAxisSize.min,
children: [ // children: [
Text( // Text(
context.translation.viewComments, // context.translation.viewComments,
style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)), // style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)),
), // ),
4.width, // 4.width,
Icon( // Icon(
Icons.arrow_forward, // Icons.arrow_forward,
color: AppColor.blueStatus(context), // color: AppColor.blueStatus(context),
size: 14, // size: 14,
) // )
], // ],
), // ),
], // ],
).paddingOnly(bottom: 16, start: 16, end: 16)) // ).paddingOnly(bottom: 16, start: 16, end: 16))
.onPress(() { // .onPress(() {
showModalBottomSheet( // showModalBottomSheet(
context: context, // context: context,
useSafeArea: true, // useSafeArea: true,
isScrollControlled: true, // isScrollControlled: true,
useRootNavigator: true, // useRootNavigator: true,
backgroundColor: Colors.transparent, // backgroundColor: Colors.transparent,
builder: (context) => GasRefillCommentsBottomSheet(requestId: gasRefillModel.id.toString()), // builder: (context) => GasRefillCommentsBottomSheet(requestId: gasRefillModel.id.toString()),
); // );
}), // }),
], ],
).toShadowContainer(context, padding: 0); ).toShadowContainer(context, padding: 0);
} }
Widget infoText({String ?label,String ?value,}){ Widget infoText({
if(value==null||value.isEmpty){ String? label,
return const SizedBox(); String? value,
} }) {
else { if (value == null || value.isEmpty) {
return const SizedBox();
} else {
return '$label: $value'.bodyText(context); return '$label: $value'.bodyText(context);
} }
} }
} }

@ -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<GasRefillForm> createState() => _GasRefillFormState();
}
class _GasRefillFormState extends State<GasRefillForm> {
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<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey _DetailsKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
bool _firstTime = true;
Lookup? _deliveredQuantity;
List<File> _attachments = [];
static List<Lookup> 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<GasRefillProvider>(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<AllRequestsProvider>(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<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(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<Lookup, NullableLoadingProvider>(
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<Lookup, GasStatusProvider>(
// 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),
),
],
),
],
],
);
}
}

@ -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/gas_refill_provider.dart';
import 'package:test_sa/controllers/providers/api/user_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/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/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart';
@ -53,13 +52,12 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
final TextEditingController _commentController = TextEditingController(); final TextEditingController _commentController = TextEditingController();
final TextEditingController _workingHoursController = TextEditingController(); final TextEditingController _workingHoursController = TextEditingController();
final GasRefillModel _formModel = GasRefillModel(gazRefillDetails: []); final GasRefillModel _formModel = GasRefillModel(gasRefillDetails: []);
final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey _DetailsKey = GlobalKey<FormState>(); final GlobalKey _DetailsKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
bool _firstTime = true; bool _firstTime = true;
Lookup? _deliveredQuantity; Lookup? _deliveredQuantity;
static List<Lookup> deliveredQuantity = [ static List<Lookup> deliveredQuantity = [
@ -77,7 +75,7 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
_formModel.fromGasRefillModel(widget.gasRefillModel!); _formModel.fromGasRefillModel(widget.gasRefillModel!);
_commentController.text = _formModel.comment ?? ""; _commentController.text = _formModel.comment ?? "";
try { 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; _currentDetails.deliverdQty = _deliveredQuantity!.value;
} catch (ex) {} } catch (ex) {}
} }
@ -101,7 +99,7 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
await Fluttertoast.showToast(msg: "Please Stop The Timer"); await Fluttertoast.showToast(msg: "Please Stop The Timer");
return false; return false;
} }
if (_formModel.gazRefillDetails?.isNotEmpty ?? false) { if (_formModel.gasRefillDetails?.isNotEmpty ?? false) {
if (!(await _addNewModel(context))) return; if (!(await _addNewModel(context))) return;
} }
@ -135,7 +133,7 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
} }
} }
bool _addNewModel(BuildContext context) { bool _addNewModel(BuildContext context) {
_validate = true; _validate = true;
if (_currentDetails.deliverdQty == null) { if (_currentDetails.deliverdQty == null) {
Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.quantity}"); Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.quantity}");
@ -147,15 +145,15 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
// return false; // return false;
// } // }
_formKey.currentState!.save(); _formKey.currentState!.save();
_currentDetails.gasType = _formModel.gazRefillDetails![0].gasType; _currentDetails.gasType = _formModel.gasRefillDetails![0].gasType;
_currentDetails.cylinderSize = _formModel.gazRefillDetails![0].cylinderSize; _currentDetails.cylinderSize = _formModel.gasRefillDetails![0].cylinderSize;
_currentDetails.cylinderType = _formModel.gazRefillDetails![0].cylinderType; _currentDetails.cylinderType = _formModel.gasRefillDetails![0].cylinderType;
_currentDetails.requestedQty = _formModel.gazRefillDetails![0].requestedQty; _currentDetails.requestedQty = _formModel.gasRefillDetails![0].requestedQty;
if (!( _currentDetails.validate(context))) { if (!(_currentDetails.validate(context))) {
setState(() {}); setState(() {});
return false; return false;
} }
_formModel.gazRefillDetails![0].deliverdQty = _currentDetails.deliverdQty; _formModel.gasRefillDetails![0].deliverdQty = _currentDetails.deliverdQty;
_validate = false; _validate = false;
// Scrollable.ensureVisible(_DetailsKey.currentContext); // Scrollable.ensureVisible(_DetailsKey.currentContext);
_deliveredQuantityController.clear(); _deliveredQuantityController.clear();
@ -176,7 +174,6 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context); _userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context); _settingProvider = Provider.of<SettingProvider>(context);
_gasRefillProvider ??= Provider.of<GasRefillProvider>(context, listen: false); _gasRefillProvider ??= Provider.of<GasRefillProvider>(context, listen: false);
@ -192,12 +189,11 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
clientName = _userProvider.user?.clientName; clientName = _userProvider.user?.clientName;
} }
HospitalsProvider().getHospitalsListByVal(searchVal: clientName ?? '').then((value) {
HospitalsProvider().getHospitalsListByVal(searchVal: clientName??'').then((value) { _gasRefillProvider!.hospital = value.firstWhere((element) => element.name == clientName, orElse: null);
_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!.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!.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);
_gasRefillProvider!.department = _gasRefillProvider!.floor?.departments?.firstWhere((element) => element.name == widget.gasRefillModel?.department?.departmentName, orElse: null);
_firstTime = false; _firstTime = false;
setState(() {}); setState(() {});
}); });
@ -226,10 +222,10 @@ class _RequestGasRefillState extends State<RequestGasRefill> {
children: [ children: [
context.translation.gasRefill.heading5(context), context.translation.gasRefill.heading5(context),
8.height, 8.height,
'${context.translation.gasRequest}: ${widget.gasRefillModel!.gazRefillDetails![0].gasType!.name}'.bodyText(context), '${context.translation.gasRequest}: ${widget.gasRefillModel!.gasRefillDetails![0].gasType!.name}'.bodyText(context),
'${context.translation.cylinderType}: ${widget.gasRefillModel!.gazRefillDetails![0].cylinderType!.name}'.bodyText(context), '${context.translation.cylinderType}: ${widget.gasRefillModel!.gasRefillDetails![0].cylinderType!.name}'.bodyText(context),
'${context.translation.cylinderSize}: ${widget.gasRefillModel!.gazRefillDetails![0].cylinderSize!.name}'.bodyText(context), '${context.translation.cylinderSize}: ${widget.gasRefillModel!.gasRefillDetails![0].cylinderSize!.name}'.bodyText(context),
'${context.translation.quantity}: ${widget.gasRefillModel!.gazRefillDetails![0].requestedQty ?? 0}'.bodyText(context), '${context.translation.quantity}: ${widget.gasRefillModel!.gasRefillDetails![0].requestedQty ?? 0}'.bodyText(context),
'${context.translation.site}: ${widget.gasRefillModel!.site?.name}'.bodyText(context), '${context.translation.site}: ${widget.gasRefillModel!.site?.name}'.bodyText(context),
], ],
).toShadowContainer(context), ).toShadowContainer(context),

@ -19,7 +19,7 @@
// //
// import '../../../models/enums/user_types.dart'; // import '../../../models/enums/user_types.dart';
// import '../../widgets/land_page/land_page_item.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'; // import 'requests/requests_page.dart';
// //
// @Deprecated("Use the page which is inside the [new_views/pages/land_page] folder") // @Deprecated("Use the page which is inside the [new_views/pages/land_page] folder")

@ -97,7 +97,7 @@ class _PpmDetailsPageState extends State<PpmDetailsPage> {
// '${context.translation.expectDate}: ${planPreventiveVisit.expectedDate?.toAssetDetailsFormat ?? ""}'.bodyText(context), //todo @baha, // '${context.translation.expectDate}: ${planPreventiveVisit.expectedDate?.toAssetDetailsFormat ?? ""}'.bodyText(context), //todo @baha,
'${context.translation.actualDate}: ${planPreventiveVisit.acutalDateOfVisit?.toIso8601String().toAssetDetailsFormat ?? ""}'.bodyText(context), //todo @baha, '${context.translation.actualDate}: ${planPreventiveVisit.acutalDateOfVisit?.toIso8601String().toAssetDetailsFormat ?? ""}'.bodyText(context), //todo @baha,
const Divider().defaultStyle(context), 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.site}: ${planPreventiveVisit.siteName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), //todo @baha,
'${context.translation.building}: ${planPreventiveVisit.buildingName?.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, '${context.translation.floor}: ${planPreventiveVisit.floorName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context), //todo @baha,
@ -106,14 +106,24 @@ class _PpmDetailsPageState extends State<PpmDetailsPage> {
], ],
).toShadowContainer(context).paddingAll(16), ).toShadowContainer(context).paddingAll(16),
).expanded, ).expanded,
if (userProvider!.user!.type == UsersTypes.engineer && (planPreventiveVisit.visitStatus!.id! != 270 && planPreventiveVisit.visitStatus!.id! != 269)) if (userProvider!.user!.type == UsersTypes.engineer && (!ppmProvider.isReadOnly))...[
AppFilledButton( AppFilledButton(
onPressed: () async { onPressed: () async {
await Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdatePpm(ppm: null, planPreventiveVisit: planPreventiveVisit))); await Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdatePpm(ppm: null, planPreventiveVisit: planPreventiveVisit)));
getVisitData(); getVisitData();
}, },
label: context.translation.updateRequest, label: context.translation.updateWorkOrder,
).paddingAll(16) ).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)
]
]); ]);
}), }),
), ),

@ -52,16 +52,8 @@ class _RoomInspectionCardState extends State<RoomInspectionCard> {
).toShadowContainer(context).paddingOnly(top: 12); ).toShadowContainer(context).paddingOnly(top: 12);
} }
Widget inspectionStatusRadioWidget({ Widget inspectionStatusRadioWidget({required int index, required PlanRecurrentMedicalTaskRoomTabAttributes model, required BuildContext context}) {
required int index, bool status = (model.attribute == null || model.attributeValue == null) ? true : (model.attribute != null ? (model.attributeValue == 'true' ? true : false) : false);
required PlanRecurrentMedicalTaskRoomTabAttributes model,
required BuildContext context,
}) {
bool status = model.attribute != null
? model.attributeValue == 'true'
? true
: false
: false;
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -71,7 +63,7 @@ class _RoomInspectionCardState extends State<RoomInspectionCard> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
model.attribute!.name!, model.attribute?.name ?? '',
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
maxLines: 1, maxLines: 1,
style: AppTextStyles.bodyText2.copyWith(color: AppColor.white936), style: AppTextStyles.bodyText2.copyWith(color: AppColor.white936),

@ -76,7 +76,8 @@ class _RoomTabsWidgetState extends State<RoomTabsWidget> {
? const ALoading().paddingOnly(top: 150) ? const ALoading().paddingOnly(top: 150)
: ListView( : ListView(
shrinkWrap: true, shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, physics: const NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
children: widget.model!.planRecurrentMedicalTaskRooms![selectedIndex].planRecurrentMedicalTaskRoomTabs!.map<Widget>((card) { children: widget.model!.planRecurrentMedicalTaskRooms![selectedIndex].planRecurrentMedicalTaskRoomTabs!.map<Widget>((card) {
return RoomInspectionCard(inspectionModel: card); return RoomInspectionCard(inspectionModel: card);
}).toList(), }).toList(),

@ -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/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_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/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/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/service_request_latest/utilities/service_request_utils.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart';
import 'package:test_sa/views/widgets/timer/app_timer.dart'; import 'package:test_sa/views/widgets/timer/app_timer.dart';
@ -40,7 +38,7 @@ class RecurrentTaskInfoWidget extends StatelessWidget {
2.height, 2.height,
'${context.translation.taskNo}: ${model!.taskNo!}'.bodyText2(context).custom(color: AppColor.neutral120), '${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.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), '${context.translation.scheduledDate}: ${model!.scheduleDate!.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120),
], ],
).toShadowContainer(context), ).toShadowContainer(context),
@ -50,17 +48,21 @@ class RecurrentTaskInfoWidget extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ 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, 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, 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, 8.height,
_timerWidget(context, model!.totalWorkingHours!) _timerWidget(context, model!.totalWorkingHours!),
8.height,
_commentWidget(context: context, model: model)
], ],
// ], // ],
).toShadowContainer(context, padding: 12) ).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, label: context.translation.timer,
timer: snapshot.recurrentWoData?.recurrentWoTimerModel, timer: snapshot.recurrentWoData?.recurrentWoTimerModel,
width: double.infinity, width: double.infinity,
// enabled: snapshot.recurrentWoData?.recurrentWoTimerModel?.endAt == null, enabled: snapshot.recurrentWoData?.status?.value != 1,
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColor.neutral100, color: AppColor.neutral100,
borderRadius: BorderRadius.circular(10), 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}) { 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, 3.height,
Text( Text(
value??'', value ?? '',
style: AppTextStyles.bodyText2.copyWith(color: AppColor.black10), style: AppTextStyles.bodyText2.copyWith(color: AppColor.black10),
) )
], ],
).toShadowContainer(context, backgroundColor: AppColor.neutral100, borderRadius: 10, paddingObject: EdgeInsets.all(12.toScreenHeight), showShadow: false); ).toShadowContainer(context, backgroundColor: AppColor.neutral100, borderRadius: 10, paddingObject: EdgeInsets.all(12.toScreenHeight), showShadow: false);
} }

@ -48,7 +48,12 @@ class _RecurrentWorkOrderViewState extends State<RecurrentWorkOrderView> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer<AllRequestsProvider>(builder: (context, requestProvider, child) { return Consumer<AllRequestsProvider>(builder: (context, requestProvider, child) {
return Scaffold( return Scaffold(
appBar: DefaultAppBar(title: context.translation.recurrentWo), appBar: DefaultAppBar(
title: context.translation.recurrentWo,
onWillPopScope: () {
_updateTask(context: context, status: 0);
},
),
body: allRequestsProvider!.isLoading body: allRequestsProvider!.isLoading
? const ALoading() ? const ALoading()
: requestProvider.recurrentWoData != null : requestProvider.recurrentWoData != null
@ -60,7 +65,6 @@ class _RecurrentWorkOrderViewState extends State<RecurrentWorkOrderView> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
RecurrentTaskInfoWidget(model: requestProvider.recurrentWoData), RecurrentTaskInfoWidget(model: requestProvider.recurrentWoData),
// 8.height,
requestProvider.recurrentWoData!.planRecurrentMedicalTaskRooms!.isNotEmpty requestProvider.recurrentWoData!.planRecurrentMedicalTaskRooms!.isNotEmpty
? Column( ? Column(
children: [ children: [
@ -72,29 +76,35 @@ class _RecurrentWorkOrderViewState extends State<RecurrentWorkOrderView> {
], ],
).paddingAll(12), ).paddingAll(12),
).paddingOnly(bottom: 85), ).paddingOnly(bottom: 85),
FooterActionButton.footerContainer( if (requestProvider.recurrentWoData?.status?.value != 1) ...[
child: Row( FooterActionButton.footerContainer(
mainAxisAlignment: MainAxisAlignment.spaceAround, child: Row(
children: [ mainAxisAlignment: MainAxisAlignment.spaceAround,
AppFilledButton( children: [
label: context.translation.save, AppFilledButton(
buttonColor: AppColor.white60, label: context.translation.save,
textColor: AppColor.black10, buttonColor: AppColor.white60,
onPressed: () => _updateTask(context: context, status: 0), textColor: AppColor.black10,
).expanded, onPressed: () => _updateTask(context: context, status: 0),
12.width, ).expanded,
AppFilledButton( 12.width,
label: context.translation.complete, AppFilledButton(
buttonColor: AppColor.primary10, label: context.translation.complete,
onPressed: () => _updateTask(context: context, status: 1), buttonColor: AppColor.primary10,
).expanded, onPressed: () => _updateTask(context: context, status: 1),
], ).expanded,
],
),
), ),
), ]
], ],
) )
: NoDataFound(message: context.translation.noDataFound).center, : 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!)) { if (validate(model: allRequestsProvider.recurrentWoData!)) {
allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers = allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers ?? []; 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()); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
allRequestsProvider.recurrentWoData?.timerModelList?.forEach((timer) { allRequestsProvider.recurrentWoData?.timerModelList?.forEach((timer) {
int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds; int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds;
allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers?.add( allRequestsProvider.recurrentWoData?.planRecurrentTaskTimers?.add(

@ -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/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_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/lookup.dart';
import 'package:test_sa/models/plan_preventive_visit/plan_preventive_visit_model.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'; import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
@ -29,7 +30,8 @@ class _PpmCalibrationToolsFormState extends State<PpmCalibrationToolsForm> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final userProvider = Provider.of<UserProvider>(context); final userProvider = Provider.of<UserProvider>(context);
int totalTabs = Provider.of<PpmProvider>(context, listen: false).totalTabs; final ppmProvider = Provider.of<PpmProvider>(context, listen: false);
int totalTabs = ppmProvider.totalTabs;
int currentIndex = totalTabs == 4 ? 2 : 1; int currentIndex = totalTabs == 4 ? 2 : 1;
return ListView.separated( return ListView.separated(
itemCount: widget.models!.length + 1, itemCount: widget.models!.length + 1,
@ -37,27 +39,30 @@ class _PpmCalibrationToolsFormState extends State<PpmCalibrationToolsForm> {
separatorBuilder: (cxt, index) => 16.height, separatorBuilder: (cxt, index) => 16.height,
itemBuilder: (context, index) { itemBuilder: (context, index) {
if (index == widget.models!.length) { if (index == widget.models!.length) {
return AppFilledButton( return Visibility(
label: "Add More Calibration Tools".addTranslation, visible: !ppmProvider.isReadOnly,
maxWidth: true, child: AppFilledButton(
textColor: AppColor.black10, label: "Add More Calibration Tools".addTranslation,
buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, maxWidth: true,
icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), textColor: AppColor.black10,
showIcon: true, buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10,
onPressed: () async { icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)),
if (widget.models?.isNotEmpty ?? false) { showIcon: true,
if (widget.models!.last.asset?.id == null) { onPressed: () async {
await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.assetNumber}"); if (widget.models?.isNotEmpty ?? false) {
return; 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) { widget.models!.add(PreventiveVisitCalibrations(id: 0));
await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.date}"); setState(() {});
return; },
} ),
}
widget.models!.add(PreventiveVisitCalibrations(id: 0));
setState(() {});
},
); );
} }
PreventiveVisitCalibrations model = widget.models![index]; PreventiveVisitCalibrations model = widget.models![index];
@ -68,48 +73,51 @@ class _PpmCalibrationToolsFormState extends State<PpmCalibrationToolsForm> {
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)],
), ),
child: Column( child: IgnorePointer(
crossAxisAlignment: CrossAxisAlignment.start, ignoring:ppmProvider.isReadOnly,
children: [ child: Column(
Row( crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
children: [ Row(
(index == 0 ? "$currentIndex /$totalTabs . Calibration Tools" : "").heading5(context), mainAxisAlignment: MainAxisAlignment.spaceBetween,
"trash".toSvgAsset(height: 20, width: 15).onPress(() { children: [
widget.models!.remove(model); (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(() {}); 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(() {});
},
),
],
), ),
); );
}, },

@ -237,6 +237,8 @@
// } // }
import 'package:flutter/material.dart'; 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/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart';
@ -289,20 +291,23 @@ class _PpmExternalDetailsFormState extends State<PpmExternalDetailsForm> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
print("widget.models!.length:${widget.models!.length}"); final ppmProvider = Provider.of<PpmProvider>(context, listen: false);
return ListView.builder( return ListView.builder(
itemCount: widget.models!.length + 1, itemCount: widget.models!.length + 1,
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
itemBuilder: (context, index) { itemBuilder: (context, index) {
if (index == widget.models!.length) { if (index == widget.models!.length) {
return AppFilledButton( return Visibility(
label: "Add More External Details".addTranslation, visible: !ppmProvider.isReadOnly,
maxWidth: true, child: AppFilledButton(
textColor: AppColor.black10, label: "Add More External Details".addTranslation,
buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, maxWidth: true,
icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), textColor: AppColor.black10,
showIcon: true, buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10,
onPressed: _addNewEntry, icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)),
showIcon: true,
onPressed: _addNewEntry,
),
); );
} }
// return !isLoading // return !isLoading
@ -336,10 +341,12 @@ class ExternalDetailItem extends StatefulWidget {
class _ExternalDetailItemState extends State<ExternalDetailItem> { class _ExternalDetailItemState extends State<ExternalDetailItem> {
TextEditingController? controller; TextEditingController? controller;
PpmProvider? _ppmProvider;
@override @override
void initState() { void initState() {
controller = TextEditingController(text: widget.model.workingHours != null ? widget.model.workingHours.toString() : ''); controller = TextEditingController(text: widget.model.workingHours != null ? widget.model.workingHours.toString() : '');
_ppmProvider= Provider.of<PpmProvider>(context,listen:false);
super.initState(); super.initState();
} }
@ -353,148 +360,151 @@ class _ExternalDetailItemState extends State<ExternalDetailItem> {
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)],
), ),
child: Column( child: IgnorePointer(
crossAxisAlignment: CrossAxisAlignment.start, ignoring: _ppmProvider!.isReadOnly,
children: [ child: Column(
Row( crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
children: [ Row(
(widget.index == 0 ? "1 /4 . External Details" : "").heading5(context), mainAxisAlignment: MainAxisAlignment.spaceBetween,
Container( children: [
height: 32, (widget.index == 0 ? "1 /4 . External Details" : "").heading5(context),
width: 32, Container(
padding: const EdgeInsets.all(6), height: 32,
child: "trash".toSvgAsset(height: 20, width: 20), width: 32,
).onPress(() { padding: const EdgeInsets.all(6),
widget.onRemove(); child: "trash".toSvgAsset(height: 20, width: 20),
}), ).onPress(() {
], widget.onRemove();
), }),
16.height, ],
SingleItemDropDownMenu<SupplierDetails, VendorProvider>( ),
context: context, 16.height,
title: context.translation.supplier, SingleItemDropDownMenu<SupplierDetails, VendorProvider>(
initialValue: widget.model.supplier, context: context,
backgroundColor: AppColor.neutral100, title: context.translation.supplier,
showAsBottomSheet: true, initialValue: widget.model.supplier,
showShadow: false, backgroundColor: AppColor.neutral100,
onSelect: (supplier) { showAsBottomSheet: true,
if (supplier != null) { showShadow: false,
setState(() { onSelect: (supplier) {
widget.model.supplier = supplier; if (supplier != null) {
}); setState(() {
} widget.model.supplier = supplier;
},
),
8.height,
SingleItemDropDownMenu<SuppPersons, NullableLoadingProvider>(
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;
},
);
}
}); });
}, }
).expanded, },
8.width, ),
ADatePicker( 8.height,
label: context.translation.endTime, SingleItemDropDownMenu<SuppPersons, NullableLoadingProvider>(
hideShadow: true, context: context,
backgroundColor: AppColor.neutral100, title: context.translation.supplierEngineer,
date: widget.model.endDateTime, enabled: widget.model.supplier != null,
formatDateWithTime: true, backgroundColor: AppColor.neutral100,
onDatePicker: (selectedDate) { initialValue: widget.model.suppPerson,
showTimePicker( staticData: widget.model.supplier?.suppPersons,
context: context, showAsBottomSheet: true,
initialTime: TimeOfDay.now(), showShadow: false,
).then((selectedTime) { onSelect: (suppPerson) {
if (selectedTime != null) { if (suppPerson != null) {
DateTime selectedDateTime = DateTime( widget.model.suppPerson = suppPerson;
selectedDate.year, }
selectedDate.month, },
selectedDate.day, ),
selectedTime.hour, 8.height,
selectedTime.minute, Row(
); mainAxisSize: MainAxisSize.min,
if (widget.model.startDateTime != null && selectedDateTime.isBefore(widget.model.startDateTime!)) { children: [
"End Date time must be greater than start date".showToast; ADatePicker(
return; 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; },
}); ).expanded,
ServiceRequestUtils.calculateAndAssignWorkingHours( 8.width,
startTime: widget.model.startDateTime, ADatePicker(
endTime: widget.model.endDateTime, label: context.translation.endTime,
workingHoursController: controller!, hideShadow: true,
updateModel: (hours) { backgroundColor: AppColor.neutral100,
widget.model.workingHours = hours; date: widget.model.endDateTime,
}, formatDateWithTime: true,
); onDatePicker: (selectedDate) {
} showTimePicker(
}); context: context,
}, initialTime: TimeOfDay.now(),
).expanded, ).then((selectedTime) {
], if (selectedTime != null) {
), DateTime selectedDateTime = DateTime(
8.height, selectedDate.year,
AppTextFormField( selectedDate.month,
labelText: context.translation.workingHours, selectedDate.day,
backgroundColor: AppColor.neutral80, selectedTime.hour,
controller: controller, selectedTime.minute,
textAlign: TextAlign.center, );
enable: false, if (widget.model.startDateTime != null && selectedDateTime.isBefore(widget.model.startDateTime!)) {
showShadow: false, "End Date time must be greater than start date".showToast;
style: Theme.of(context).textTheme.titleMedium, return;
), }
8.height, 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,
],
),
), ),
); );
} }

@ -32,6 +32,7 @@ class _PpmPmChecklistFormState extends State<PpmPmChecklistForm> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
int totalTabs = Provider.of<PpmProvider>(context, listen: false).totalTabs; int totalTabs = Provider.of<PpmProvider>(context, listen: false).totalTabs;
final ppmProvider = Provider.of<PpmProvider>(context, listen: false);
int currentIndex = totalTabs == 4 ? 4 : 3; int currentIndex = totalTabs == 4 ? 4 : 3;
List<PreventiveVisitChecklists>? list = widget.checkList ?? []; List<PreventiveVisitChecklists>? list = widget.checkList ?? [];
return (list.isEmpty) return (list.isEmpty)
@ -42,68 +43,71 @@ class _PpmPmChecklistFormState extends State<PpmPmChecklistForm> {
shrinkWrap: true, shrinkWrap: true,
separatorBuilder: (cxt, index) => 12.height, separatorBuilder: (cxt, index) => 12.height,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return Column( return IgnorePointer(
mainAxisSize: MainAxisSize.min, ignoring: ppmProvider.isReadOnly,
crossAxisAlignment: CrossAxisAlignment.start, child: Column(
children: [ mainAxisSize: MainAxisSize.min,
if (index == 0) ...[ crossAxisAlignment: CrossAxisAlignment.start,
"$currentIndex /$totalTabs . PM Checklist".heading5(context), children: [
16.height, 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<Lookup, PpmChecklistStatusProvider>(
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( ).toShadowContainer(context, showShadow: false, borderRadius: 20),
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<Lookup, PpmChecklistStatusProvider>(
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);
}, },
); );
} }

@ -26,7 +26,8 @@ class PpmPMKitsForm extends StatefulWidget {
class _PpmPMKitsFormState extends State<PpmPMKitsForm> { class _PpmPMKitsFormState extends State<PpmPMKitsForm> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
int totalTabs = Provider.of<PpmProvider>(context, listen: false).totalTabs; final ppmProvider = Provider.of<PpmProvider>(context, listen: false);
int totalTabs = ppmProvider.totalTabs;
int currentIndex = totalTabs == 4 ? 3 : 2; int currentIndex = totalTabs == 4 ? 3 : 2;
return ListView.builder( return ListView.builder(
itemCount: widget.models!.length + 1, itemCount: widget.models!.length + 1,
@ -34,27 +35,30 @@ class _PpmPMKitsFormState extends State<PpmPMKitsForm> {
padding: const EdgeInsets.only(left: 16, right: 16, top: 8, bottom: 16), padding: const EdgeInsets.only(left: 16, right: 16, top: 8, bottom: 16),
itemBuilder: (context, index) { itemBuilder: (context, index) {
if (index == widget.models!.length) { if (index == widget.models!.length) {
return AppFilledButton( return Visibility(
label: "Add More PM Kits".addTranslation, visible: !ppmProvider.isReadOnly,
maxWidth: true, child: AppFilledButton(
textColor: AppColor.black10, label: "Add More PM Kits".addTranslation,
buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10, maxWidth: true,
icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)), textColor: AppColor.black10,
showIcon: true, buttonColor: context.isDark ? AppColor.neutral60 : AppColor.white10,
onPressed: () async { icon: Icon(Icons.add_circle, color: AppColor.blueStatus(context)),
if (widget.models?.isNotEmpty ?? false) { showIcon: true,
if (widget.models!.last.partCatalogItem?.partNumber == null) { onPressed: () async {
await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.partNumber}"); if (widget.models?.isNotEmpty ?? false) {
return; 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) { widget.models!.add(PreventiveVisitKits(id: 0));
await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.partName}"); setState(() {});
return; },
} ),
}
widget.models!.add(PreventiveVisitKits(id: 0));
setState(() {});
},
); );
} }
final model = widget.models![index]; final model = widget.models![index];
@ -66,47 +70,50 @@ class _PpmPMKitsFormState extends State<PpmPMKitsForm> {
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)],
), ),
child: Column( child: IgnorePointer(
crossAxisAlignment: CrossAxisAlignment.start, ignoring: ppmProvider.isReadOnly,
children: [ child: Column(
Row( crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
children: [ Row(
(index == 0 ? "$currentIndex /$totalTabs . PM Kits" : "").heading5(context), mainAxisAlignment: MainAxisAlignment.spaceBetween,
Container( children: [
height: 32, (index == 0 ? "$currentIndex /$totalTabs . PM Kits" : "").heading5(context),
width: 32, Container(
padding: const EdgeInsets.all(6), height: 32,
child: "trash".toSvgAsset(height: 20, width: 20), width: 32,
).onPress(() { padding: const EdgeInsets.all(6),
widget.models!.remove(model); 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(() {}); 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(() {});
},
),
],
), ),
); );
}, },

@ -1,5 +1,4 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.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/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/widget_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/plan_preventive_visit/plan_preventive_visit_model.dart';
import 'package:test_sa/models/ppm/ppm.dart'; import 'package:test_sa/models/ppm/ppm.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
@ -44,8 +42,7 @@ class _UpdatePpmState extends State<UpdatePpm> with TickerProviderStateMixin {
late PpmProvider ppmProvider; late PpmProvider ppmProvider;
_onSubmit({required int status}) async { _onSubmit({required int status}) async {
if (ppmProvider.validate()) {
if(ppmProvider.validate()){
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading()); showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
ppmProvider.planPreventiveVisit?.preventiveVisitAttachments = []; ppmProvider.planPreventiveVisit?.preventiveVisitAttachments = [];
for (var item in ppmProvider.ppmPlanAttachments) { for (var item in ppmProvider.ppmPlanAttachments) {
@ -67,7 +64,7 @@ class _UpdatePpmState extends State<UpdatePpm> with TickerProviderStateMixin {
}); });
await ppmProvider.updateVisitByEngineer(status: status).whenComplete(() { await ppmProvider.updateVisitByEngineer(status: status).whenComplete(() {
if(status==1){ if (status == 1) {
AllRequestsProvider allRequestsProvider = Provider.of<AllRequestsProvider>(context, listen: false); AllRequestsProvider allRequestsProvider = Provider.of<AllRequestsProvider>(context, listen: false);
allRequestsProvider.reset(); allRequestsProvider.reset();
allRequestsProvider.getAllRequests(context, typeTransaction: 4); allRequestsProvider.getAllRequests(context, typeTransaction: 4);
@ -78,15 +75,16 @@ class _UpdatePpmState extends State<UpdatePpm> with TickerProviderStateMixin {
Navigator.pop(context); Navigator.pop(context);
}); });
} }
} }
@override @override
void initState() { void initState() {
ppmProvider = Provider.of<PpmProvider>(context, listen: false); ppmProvider = Provider.of<PpmProvider>(context, listen: false);
_planPreventiveVisit = widget.planPreventiveVisit; _planPreventiveVisit = widget.planPreventiveVisit;
initTabs(_planPreventiveVisit.typeOfService); // WidgetsBinding.instance.addPostFrameCallback((_) {
initTabs(_planPreventiveVisit.typeOfService);
// });
super.initState(); super.initState();
} }
@ -115,7 +113,12 @@ class _UpdatePpmState extends State<UpdatePpm> with TickerProviderStateMixin {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: AppColor.neutral110, backgroundColor: AppColor.neutral110,
appBar: DefaultAppBar(title: context.translation.preventiveMaintenance), appBar: DefaultAppBar(
title: context.translation.preventiveMaintenance,
onWillPopScope:ppmProvider.isReadOnly?null: () {
_onSubmit(status: 0);
},
),
key: _scaffoldKey, key: _scaffoldKey,
body: SafeArea( body: SafeArea(
child: Column( child: Column(
@ -158,6 +161,7 @@ class _UpdatePpmState extends State<UpdatePpm> with TickerProviderStateMixin {
), ),
), ),
TabBarView( TabBarView(
physics: const NeverScrollableScrollPhysics(),
children: [ children: [
WoInfoForm( WoInfoForm(
planPreventiveVisit: _planPreventiveVisit, planPreventiveVisit: _planPreventiveVisit,
@ -183,35 +187,72 @@ class _UpdatePpmState extends State<UpdatePpm> with TickerProviderStateMixin {
).expanded, ).expanded,
Row( Row(
children: [ children: [
AppFilledButton( if (tabIndex == 1) ...[
buttonColor: AppColor.white60, AppFilledButton(
textColor: AppColor.neutral50, buttonColor: _tabController!.index == 0 ? null : AppColor.background(context),
onPressed: () { textColor: _tabController!.index == 0 ? null : AppColor.blueStatus(context),
_onSubmit(status: 0); showBorder: true,
}, disableButton: _tabController!.index == 0,
label: context.translation.save, onPressed: () {
).expanded, if (_tabController!.index == 0) {
16.width, return;
AppFilledButton( }
onPressed: () { _tabController?.animateTo(_tabController!.index - 1);
if (tabIndex == 0) {
_onSubmit(status: 1);
return;
}
if (ppmProvider.totalTabs == _tabController!.index + 1) {
_onSubmit(status: 1);
} else {
_tabController?.animateTo(_tabController!.index + 1);
setState(() {}); setState(() {});
} return;
}, },
label: tabIndex == 0 ? "Complete".addTranslation : ((ppmProvider.totalTabs == _tabController!.index + 1) ? "Complete".addTranslation : context.translation.next), label: context.translation.back,
).expanded, ).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), ).toShadowContainer(context, showShadow: false, borderRadius: 0),
], ],
), ),
), ),
); ).handlePopScope(cxt: context, showPopUp:!ppmProvider.isReadOnly ,onSave: () {
_onSubmit(status: 0);
});
} }
} }

@ -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/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_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/text_extensions.dart';
import 'package:test_sa/extensions/widget_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/models/plan_preventive_visit/plan_preventive_visit_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/providers/ppm_asset_availability_provider.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_service_provider.dart';
import 'package:test_sa/providers/ppm_task_status_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/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/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/images/multi_image_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/views/widgets/requests/request_status.dart';
import 'package:test_sa/models/device/asset.dart';
import '../../../../../models/lookup.dart'; import '../../../../../models/lookup.dart';
import '../../../../../new_views/common_widgets/app_text_form_field.dart'; import '../../../../../new_views/common_widgets/app_text_form_field.dart';
@ -36,8 +45,6 @@ class WoInfoForm extends StatefulWidget {
} }
class _WoInfoFormState extends State<WoInfoForm> { class _WoInfoFormState extends State<WoInfoForm> {
//TODO need to move this to provider ...
@override @override
void initState() { void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) async { WidgetsBinding.instance.addPostFrameCallback((_) async {
@ -56,218 +63,240 @@ class _WoInfoFormState extends State<WoInfoForm> {
double totalWorkingHours = double totalWorkingHours =
widget.planPreventiveVisit.preventiveVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0; 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<PpmProvider>(builder: (context, ppmProvider, child) { return Consumer<PpmProvider>(builder: (context, ppmProvider, child) {
return ListView( return ListView(
padding: const EdgeInsets.only(left: 16, right: 16, top: 8, bottom: 16), padding: const EdgeInsets.only(left: 16, right: 16, top: 8, bottom: 16),
children: [ children: [
Column( IgnorePointer(
mainAxisSize: MainAxisSize.min, ignoring: ppmProvider.isReadOnly,
crossAxisAlignment: CrossAxisAlignment.start, child: Column(
children: [ children: [
if (widget.planPreventiveVisit.visitStatus != null) Column(
StatusLabel( mainAxisSize: MainAxisSize.min,
label: widget.planPreventiveVisit.visitStatus?.name, crossAxisAlignment: CrossAxisAlignment.start,
textColor: AppColor.getRequestStatusTextColorByName(context, widget.planPreventiveVisit.visitStatus?.name), children: [
backgroundColor: AppColor.getRequestStatusColorByName(context, widget.planPreventiveVisit.visitStatus?.name), if (widget.planPreventiveVisit.visitStatus != null)
), StatusLabel(
8.height, label: widget.planPreventiveVisit.visitStatus?.name,
widget.planPreventiveVisit.planName!.bodyText(context).custom(color: AppColor.black10), textColor: AppColor.getRequestStatusTextColorByName(context, widget.planPreventiveVisit.visitStatus?.name),
2.height, backgroundColor: AppColor.getRequestStatusColorByName(context, widget.planPreventiveVisit.visitStatus?.name),
'${context.translation.pmPlanNo}: ${widget.planPreventiveVisit.planNo}'.bodyText2(context).custom(color: AppColor.neutral120), ),
//need to add in translation it's suggestion from ahmed.. 8.height,
'Work Order Number: ${widget.planPreventiveVisit.visitNo}'.bodyText2(context).custom(color: AppColor.neutral120), widget.planPreventiveVisit.planName!.bodyText(context).custom(color: AppColor.black10),
'${context.translation.from}: ${widget.planPreventiveVisit.fromDate?.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120), 2.height,
'${context.translation.to}: ${widget.planPreventiveVisit.toDate?.toMonthYearFormat}'.bodyText2(context).custom(color: AppColor.neutral120), '${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 : '-'}' '${context.translation.nextPmDate}: ${widget.planPreventiveVisit.nextPMDate != null ? widget.planPreventiveVisit.nextPMDate!.toMonthYearFormat : '-'}'
.bodyText2(context) .bodyText2(context)
.custom(color: AppColor.neutral120), .custom(color: AppColor.neutral120),
'${context.translation.assignEngineer}: ${widget.planPreventiveVisit.assignedEmployee?.userName ?? ""}'.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), '${context.translation.executionTimeFrame}: ${widget.planPreventiveVisit.executionTimeFrame ?? ""} days'.bodyText2(context).custom(color: AppColor.neutral120),
], ],
).toShadowContainer(context), ).toShadowContainer(context),
12.height, 12.height,
Column( Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
widget.planPreventiveVisit.assetName!.bodyText(context).custom(color: AppColor.black10), widget.planPreventiveVisit.assetName!.bodyText(context).custom(color: AppColor.black10),
"info_icon".toSvgAsset(height: 17, width: 17), "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...
2.height, showModalBottomSheet(
'${context.translation.assetNo}: ${widget.planPreventiveVisit.asset?.assetNumber}'.bodyText2(context).custom(color: AppColor.neutral120), context: context,
'${context.translation.model}: ${widget.planPreventiveVisit.model}'.bodyText2(context).custom(color: AppColor.neutral120), isScrollControlled: true,
], shape: const RoundedRectangleBorder(
).toShadowContainer(context), 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<Lookup, PPMVisitStatusProvider>( // SingleItemDropDownMenu<Lookup, PPMVisitStatusProvider>(
// context: context, // context: context,
// initialValue: // initialValue:
// widget.planPreventiveVisit.visitStatus?.id == null ? null : Lookup(name: widget.planPreventiveVisit.visitStatus?.name ?? "", id: widget.planPreventiveVisit.visitStatus?.id?.toInt()), // widget.planPreventiveVisit.visitStatus?.id == null ? null : Lookup(name: widget.planPreventiveVisit.visitStatus?.name ?? "", id: widget.planPreventiveVisit.visitStatus?.id?.toInt()),
// title: context.translation.ppmVisit, // title: context.translation.ppmVisit,
// onSelect: (value) { // onSelect: (value) {
// if (value?.value == 4) { // if (value?.value == 4) {
// "Status cannot be change to ${value?.name}.".addTranslation.showToast; // "Status cannot be change to ${value?.name}.".addTranslation.showToast;
// setState(() {}); // setState(() {});
// return; // return;
// } // }
// //
// if (value != null) { // if (value != null) {
// widget.planPreventiveVisit.visitStatus?.name = value.name; // widget.planPreventiveVisit.visitStatus?.name = value.name;
// widget.planPreventiveVisit.visitStatus?.id = value.id; // widget.planPreventiveVisit.visitStatus?.id = value.id;
// } // }
// }, // },
// ), // ),
// SingleItemDropDownMenu<Lookup, PPMDeviceStatusProvider>( // SingleItemDropDownMenu<Lookup, PPMDeviceStatusProvider>(
// context: context, // context: context,
// initialValue: widget.planPreventiveVisit.deviceStatusId == null ? null : Lookup(name: widget.model.deviceStatusName ?? "", id: widget.model.deviceStatusId?.toInt()), // initialValue: widget.planPreventiveVisit.deviceStatusId == null ? null : Lookup(name: widget.model.deviceStatusName ?? "", id: widget.model.deviceStatusId?.toInt()),
// title: context.translation.deviceStatus, // title: context.translation.deviceStatus,
// onSelect: (value) { // onSelect: (value) {
// if (value != null) { // if (value != null) {
// widget.planPreventiveVisit.deviceStatusId = value.id; // widget.planPreventiveVisit.deviceStatusId = value.id;
// widget.planPreventiveVisit.deviceStatusName = value.name; // widget.planPreventiveVisit.deviceStatusName = value.name;
// } // }
// }, // },
// ), // ),
8.height, 8.height,
Column( Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
//TODO Ahmed need to provide look up value.... SingleItemDropDownMenu<Lookup, PpmTaskStatusProvider>(
context: context,
SingleItemDropDownMenu<Lookup, PpmTaskStatusProvider>( showShadow: false,
context: context, initialValue: widget.planPreventiveVisit.taskStatus == null ? null : Lookup(name: widget.planPreventiveVisit.taskStatus?.name ?? "", id: widget.planPreventiveVisit.taskStatus?.id),
showShadow: false, title: context.translation.pmTestResult,
initialValue: widget.planPreventiveVisit.taskStatus == null ? null : Lookup(name: widget.planPreventiveVisit.taskStatus?.name ?? "", id: widget.planPreventiveVisit.taskStatus?.id), backgroundColor: AppColor.neutral100,
title: context.translation.pmTestResult, onSelect: (value) {
backgroundColor: AppColor.neutral100, if (value != null) {
onSelect: (value) { widget.planPreventiveVisit.taskStatus = value;
if (value != null) { }
widget.planPreventiveVisit.taskStatus = value; },
} ),
}, 8.height,
), ADatePicker(
8.height, label: context.translation.actualVisit,
ADatePicker( hideShadow: true,
label: context.translation.actualVisit, backgroundColor: AppColor.neutral100,
hideShadow: true, date: widget.planPreventiveVisit.acutalDateOfVisit,
backgroundColor: AppColor.neutral100, formatDateWithTime: true,
date: widget.planPreventiveVisit.acutalDateOfVisit, onDatePicker: (selectedDate) {
formatDateWithTime: true, showTimePicker(
onDatePicker: (selectedDate) { context: context,
showTimePicker( initialTime: TimeOfDay.now(),
context: context, ).then((selectedTime) {
initialTime: TimeOfDay.now(), if (selectedTime != null) {
).then((selectedTime) { DateTime selectedDateTime = DateTime(
if (selectedTime != null) { selectedDate.year,
DateTime selectedDateTime = DateTime( selectedDate.month,
selectedDate.year, selectedDate.day,
selectedDate.month, selectedTime.hour,
selectedDate.day, selectedTime.minute,
selectedTime.hour, );
selectedTime.minute, setState(() {
); widget.planPreventiveVisit.acutalDateOfVisit = selectedDateTime;
setState(() { });
widget.planPreventiveVisit.acutalDateOfVisit = selectedDateTime; }
}); });
} },
}); ),
}, // SingleItemDropDownMenu<Lookup, PpmElectricalSafetyProvider>(
), // context: context,
// SingleItemDropDownMenu<Lookup, PpmElectricalSafetyProvider>( // backgroundColor: AppColor.neutral100,
// context: context, // initialValue: widget.planPreventiveVisit.safety?.id == null ? null : Lookup(name: widget.planPreventiveVisit.safety?.name ?? "", id: widget.planPreventiveVisit.safety?.id),
// backgroundColor: AppColor.neutral100, // title: context.translation.actualVisit,
// initialValue: widget.planPreventiveVisit.safety?.id == null ? null : Lookup(name: widget.planPreventiveVisit.safety?.name ?? "", id: widget.planPreventiveVisit.safety?.id), // onSelect: (value) {
// title: context.translation.actualVisit, // if (value != null) {
// onSelect: (value) { // widget.planPreventiveVisit.safety = value;
// if (value != null) { // // widget.planPreventiveVisit.safety?.id = value.id;
// widget.planPreventiveVisit.safety = value; // // widget.planPreventiveVisit.safety?.name = value.name;
// // widget.planPreventiveVisit.safety?.id = value.id; // }
// // widget.planPreventiveVisit.safety?.name = value.name; // },
// } // ),
// },
// ),
8.height, 8.height,
SingleItemDropDownMenu<Lookup, PpmElectricalSafetyProvider>( SingleItemDropDownMenu<Lookup, PpmElectricalSafetyProvider>(
context: context, context: context,
backgroundColor: AppColor.neutral100, backgroundColor: AppColor.neutral100,
showShadow: false, showShadow: false,
initialValue: widget.planPreventiveVisit.safety?.id == null ? null : Lookup(name: widget.planPreventiveVisit.safety?.name ?? "", id: widget.planPreventiveVisit.safety?.id), initialValue: widget.planPreventiveVisit.safety?.id == null ? null : Lookup(name: widget.planPreventiveVisit.safety?.name ?? "", id: widget.planPreventiveVisit.safety?.id),
title: "Electrical Safety", title: "Electrical Safety",
onSelect: (value) { onSelect: (value) {
if (value != null) { if (value != null) {
widget.planPreventiveVisit.safety = value; widget.planPreventiveVisit.safety = value;
} }
}, },
), ),
8.height, 8.height,
SingleItemDropDownMenu<Lookup, PpmAssetAvailabilityProvider>( SingleItemDropDownMenu<Lookup, PpmAssetAvailabilityProvider>(
context: context, context: context,
backgroundColor: AppColor.neutral100, backgroundColor: AppColor.neutral100,
showShadow: false, showShadow: false,
initialValue: widget.planPreventiveVisit.assetAvailability == null initialValue: widget.planPreventiveVisit.assetAvailability == null
? null ? null
: Lookup(name: widget.planPreventiveVisit.assetAvailability?.name ?? "", id: widget.planPreventiveVisit.assetAvailability?.id), : Lookup(name: widget.planPreventiveVisit.assetAvailability?.name ?? "", id: widget.planPreventiveVisit.assetAvailability?.id),
title: "Asset Availability", title: "Asset Availability",
onSelect: (value) { onSelect: (value) {
if (value != null) { if (value != null) {
widget.planPreventiveVisit.assetAvailability = value; widget.planPreventiveVisit.assetAvailability = value;
} }
}, },
), ),
8.height, 8.height,
SingleItemDropDownMenu<Lookup, PpmServiceProvider>( SingleItemDropDownMenu<Lookup, PpmServiceProvider>(
context: context, context: context,
backgroundColor: AppColor.neutral100, backgroundColor: AppColor.neutral100,
showShadow: false, showShadow: false,
initialValue: widget.planPreventiveVisit.typeOfService == null initialValue: widget.planPreventiveVisit.typeOfService == null
? null ? null
: Lookup(name: widget.planPreventiveVisit.typeOfService?.name ?? "", id: widget.planPreventiveVisit.typeOfService?.id?.toInt()), : Lookup(name: widget.planPreventiveVisit.typeOfService?.name ?? "", id: widget.planPreventiveVisit.typeOfService?.id?.toInt()),
title: context.translation.typeOfPm, title: context.translation.typeOfPm,
onSelect: (value) { onSelect: (value) {
if (value != null) { if (value != null) {
widget.planPreventiveVisit.typeOfService = value; widget.planPreventiveVisit.typeOfService = value;
if (widget.planPreventiveVisit.typeOfService?.id == 66) { if (widget.planPreventiveVisit.typeOfService?.id == 66) {
ppmProvider.totalTabs = 4; ppmProvider.totalTabs = 4;
} else { } else {
ppmProvider.totalTabs = 3; ppmProvider.totalTabs = 3;
} }
widget.onTypeOfServiceChange!(value); widget.onTypeOfServiceChange!(value);
} }
}, },
), ),
8.height, 8.height,
_timerWidget(context, totalWorkingHours), _timerWidget(context, totalWorkingHours),
8.height, 8.height,
AppTextFormField( AppTextFormField(
labelText: context.translation.callComments, labelText: context.translation.comment,
backgroundColor: AppColor.neutral100, backgroundColor: AppColor.neutral100,
showShadow: false, showShadow: false,
initialValue: (widget.planPreventiveVisit.comments ?? "").toString(), initialValue: (widget.planPreventiveVisit.comments ?? "").toString(),
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleMedium, style: Theme.of(context).textTheme.titleMedium,
onChange: (value) { onChange: (value) {
widget.planPreventiveVisit.comments = value; widget.planPreventiveVisit.comments = value;
}, },
), ),
16.height, 16.height,
MultiFilesPicker( MultiFilesPicker(
label: context.translation.attachments, label: context.translation.attachments,
files: ppmProvider.ppmPlanAttachments, files: ppmProvider.ppmPlanAttachments,
buttonColor: AppColor.black10, buttonColor: AppColor.black10,
onlyImages: false, onlyImages: false,
buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120), buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120),
), ),
], ],
).toShadowContainer(context), ).toShadowContainer(context),
],
),
),
//TODO need to check this also... //TODO need to check this also...
// ESignature( // ESignature(
// title: context.translation.nurseSignature, // title: context.translation.nurseSignature,
@ -292,6 +321,33 @@ class _WoInfoFormState extends State<WoInfoForm> {
}); });
} }
_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<Asset> getAssetById () async {
// Asset asset = Asset();
// AssetProvider _assetProvider = Provider.of<AssetProvider>(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) { Widget _timerWidget(BuildContext context, double totalWorkingHours) {
return Column( return Column(
children: [ children: [

@ -18,7 +18,7 @@ class PendingServiceRequestScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: DefaultAppBar(title: "Pending Requests (${pendingAssetServiceRequest.details!.length})"), appBar: DefaultAppBar(title: "Pending WOs (${pendingAssetServiceRequest.details!.length})"),
body: ListView.separated( body: ListView.separated(
itemCount: pendingAssetServiceRequest.details!.length, itemCount: pendingAssetServiceRequest.details!.length,
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),

@ -48,9 +48,9 @@ class AssetDetailBottomSheet extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
"${context.translation.assetNo}: ${asset!.assetNumber}".bodyText(context), "${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.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), //"${context.translation.location}: ${assetModel.site.custName?.cleanupWhitespace?.capitalizeFirstOfEach}".bodyText(context),
], ],
).expanded, ).expanded,

@ -25,7 +25,7 @@ class PendingRequestBottomSheet extends StatelessWidget {
"Alert!".heading4(context), "Alert!".heading4(context),
12.height, 12.height,
Text( Text(
"${pendingAssetServiceRequest.details!.length} pending service requests found", "${pendingAssetServiceRequest.details!.length} pending corrective maintenance found",
style: TextStyle( style: TextStyle(
fontSize: 16.toScreenWidth, fontSize: 16.toScreenWidth,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,

@ -19,6 +19,7 @@ class AssetPicker extends StatelessWidget {
final bool showAssetInfo; final bool showAssetInfo;
final Color? borderColor; final Color? borderColor;
final Color? buttonColor; final Color? buttonColor;
Color? backgroundColor;
final bool forPPM; final bool forPPM;
final bool showLoading; final bool showLoading;
final bool multiSelection; final bool multiSelection;
@ -33,6 +34,7 @@ class AssetPicker extends StatelessWidget {
this.onAssetRemove, this.onAssetRemove,
this.borderColor, this.borderColor,
this.buttonColor, this.buttonColor,
this.backgroundColor,
this.showAssetInfo = true, this.showAssetInfo = true,
this.multiSelection = false, this.multiSelection = false,
this.forPPM = false, this.forPPM = false,
@ -53,7 +55,7 @@ class AssetPicker extends StatelessWidget {
height: 50, height: 50,
alignment: Alignment.center, alignment: Alignment.center,
decoration: BoxDecoration( decoration: BoxDecoration(
color: buttonColor ?? AppColor.blueStatus(context), color: buttonColor ?? backgroundColor?? AppColor.blueStatus(context),
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)], // boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)],
), ),

@ -54,7 +54,7 @@ class _CommissioningStatusButtonsState extends State<CommissioningStatusButtons>
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
context.translation.equipmentStatus.heading5(context).paddingOnly(start: 16, end: 16), context.translation.assetStatus.heading5(context).paddingOnly(start: 16, end: 16),
8.height, 8.height,
Consumer<CommissioningStatusProvider>( Consumer<CommissioningStatusProvider>(
builder: (context, snapshot, _) { builder: (context, snapshot, _) {

@ -41,7 +41,7 @@ class GasRefillItem extends StatelessWidget {
), ),
8.height, 8.height,
context.translation.gasRefillRequest.heading5(context), 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), '${context.translation.site}: ${item.site!.name}'.bodyText(context),
8.height, 8.height,
Row( Row(

@ -18,6 +18,7 @@ class MultiFilesPicker extends StatefulWidget {
final String label; final String label;
final bool error; final bool error;
final List<File> files; final List<File> files;
final List<AttachmentModel> attachment ;
final bool enabled, onlyImages; final bool enabled, onlyImages;
double? buttonHeight; double? buttonHeight;
Widget? buttonIcon; Widget? buttonIcon;
@ -28,6 +29,7 @@ class MultiFilesPicker extends StatefulWidget {
MultiFilesPicker( MultiFilesPicker(
{Key? key, {Key? key,
this.files = const <File>[], this.files = const <File>[],
this.attachment = const <AttachmentModel>[],
required this.label, required this.label,
this.error = false, this.error = false,
this.buttonHeight, this.buttonHeight,
@ -49,17 +51,19 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
AppDashedButton( if(widget.enabled)...[
title: widget.label, AppDashedButton(
height: widget.buttonHeight, title: widget.label,
buttonColor: widget.buttonColor, height: widget.buttonHeight,
icon: widget.buttonIcon, buttonColor: widget.buttonColor,
onPressed: (widget.enabled == false) icon: widget.buttonIcon,
? () {} onPressed: (widget.enabled == false)
: widget.showAsGrid ? () {}
? showFileSourceSheet : widget.showAsGrid
: onFilePicker), ? showFileSourceSheet
16.height, : onFilePicker),
16.height,
],
if (widget.files.isNotEmpty) if (widget.files.isNotEmpty)
Wrap( Wrap(
spacing: 8.toScreenWidth, spacing: 8.toScreenWidth,
@ -123,10 +127,10 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> {
"Attach File".heading4(context), "Attach File".heading4(context),
12.height, 12.height,
GridView( GridView(
padding: EdgeInsets.all(0), padding: const EdgeInsets.all(0),
shrinkWrap: true, shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(), 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: <Widget>[ children: <Widget>[
gridItem(Icons.camera_enhance_rounded, context.translation.pickFromCamera).onPress(() => Navigator.of(context).pop(ImageSource.camera)), 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.image_rounded, context.translation.pickFromGallery).onPress(() => Navigator.of(context).pop(ImageSource.gallery)),
@ -141,38 +145,34 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> {
).paddingAll(21), ).paddingAll(21),
)) as ImageSource; )) as ImageSource;
if (source == null) return;
final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800); final pickedFile = await ImagePicker().pickImage(source: source, imageQuality: 70, maxWidth: 800, maxHeight: 800);
if (pickedFile != null) { if (pickedFile != null) {
File fileImage = File(pickedFile.path); File fileImage = File(pickedFile.path);
if (fileImage != null) { widget.files.add(fileImage);
widget.files.add(fileImage); if (widget.onChange != null) {
if (widget.onChange != null) { widget.onChange!(widget.files);
widget.onChange!(widget.files);
}
setState(() {});
} }
} setState(() {});
}
} }
Widget gridItem(IconData iconData, String title) { Widget gridItem(IconData iconData, String title) {
return Container( return Container(
padding: EdgeInsets.all(12), padding: const EdgeInsets.all(12),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
border: Border.all(color: Color(0xffF1F1F1), width: 1), border: Border.all(color: const Color(0xffF1F1F1), width: 1),
), ),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Icon(iconData, color: Color(0xff7D859A), size: 36), Icon(iconData, color: const Color(0xff7D859A), size: 36),
Text( Text(
title, title,
style: TextStyle(fontSize: 12, fontWeight: FontWeight.w500), style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
), ),
], ],
), ),
@ -285,3 +285,295 @@ class _MultiFilesPickerState extends State<MultiFilesPicker> {
setState(() {}); setState(() {});
} }
} }
class AttachmentModel {
int id =0;
File ? file;
AttachmentModel(this.id,this.file);
factory AttachmentModel.fromJson(Map<String, dynamic> json) {
return AttachmentModel(
json['id'] ?? 0,
json['file'] != null ? File(json['file']) : null,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'file': file?.path,
};
}
}
class AttachmentPicker extends StatefulWidget {
final String label;
final bool error;
final List<AttachmentModel> attachment ;
final bool enabled, onlyImages;
double? buttonHeight;
Widget? buttonIcon;
Color? buttonColor;
final Function(List<AttachmentModel>)? onChange;
final bool showAsGrid;
AttachmentPicker(
{Key? key,
this.attachment = const <AttachmentModel>[],
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<AttachmentPicker> createState() => _AttachmentPickerState();
}
class _AttachmentPickerState extends State<AttachmentPicker> {
@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: <Widget>[
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<ImageSource>(
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: <Widget>[
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: <Widget>[
// 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(() {});
}
}

@ -32,6 +32,7 @@ class _AutoCompletePartsFieldState extends State<AutoCompletePartsField> {
@override @override
void initState() { void initState() {
print('initial value i got is ${widget.initialValue}');
_controller = TextEditingController(text: widget.initialValue); _controller = TextEditingController(text: widget.initialValue);
super.initState(); super.initState();
} }

@ -18,8 +18,9 @@ class AssistantEmployeeMenu extends StatefulWidget {
final String? title; // Now nullable final String? title; // Now nullable
final bool enable; final bool enable;
final bool showAsBottomSheet; 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); : super(key: key);
@override @override
@ -74,7 +75,7 @@ class _SingleAssistantEmployeeMenuState extends State<AssistantEmployeeMenu> {
decoration: BoxDecoration( decoration: BoxDecoration(
color: widget.backgroundColor ?? (context.isDark ? AppColor.neutral50 : AppColor.neutral120), color: widget.backgroundColor ?? (context.isDark ? AppColor.neutral50 : AppColor.neutral120),
borderRadius: BorderRadius.circular(10), 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( child: Stack(
alignment: Alignment.center, alignment: Alignment.center,

@ -31,6 +31,7 @@ class ServiceReportAssistantEmployeeMenu extends StatelessWidget {
initialStatus: initialValue, initialStatus: initialValue,
title: title, title: title,
showAsBottomSheet: true, showAsBottomSheet: true,
hideShadow: true,
statuses: menuProvider.assistantEmployees ?? [], statuses: menuProvider.assistantEmployees ?? [],
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
// Provide an empty list if null // Provide an empty list if null

@ -1213,6 +1213,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.2" 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: pinput:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1506,22 +1514,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.0" 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: synchronized:
dependency: transitive dependency: transitive
description: description:

@ -79,11 +79,11 @@ dependencies:
image_cropper: ^8.0.2 image_cropper: ^8.0.2
flutter_timezone: ^3.0.1 flutter_timezone: ^3.0.1
device_calendar: ^4.3.3 device_calendar: ^4.3.3
pie_chart: ^5.4.0
badges: ^3.1.1 badges: ^3.1.1
# buttons_tabbar: ^1.1.2 # buttons_tabbar: ^1.1.2
flutter_custom_month_picker: ^0.1.3 flutter_custom_month_picker: ^0.1.3
syncfusion_flutter_charts: ^26.2.14
local_auth: ^2.3.0 local_auth: ^2.3.0
google_api_availability: ^5.0.0 google_api_availability: ^5.0.0
huawei_push: ^6.5.0+300 huawei_push: ^6.5.0+300

Loading…
Cancel
Save