diff --git a/assets/subtitles/ar_subtitle.json b/assets/subtitles/ar_subtitle.json index ada5f900..b4294845 100644 --- a/assets/subtitles/ar_subtitle.json +++ b/assets/subtitles/ar_subtitle.json @@ -188,5 +188,7 @@ "alert": "تنبيه", "duplicateAlert": "تنبيه التكرار", "duplicateAlertMessage": "هل أنت متأكد أنك تريد تكرار الطلب؟", - "duplicateRequest": "تكرار الطلب" + "duplicateRequest": "تكرار الطلب", + "comment" : "تعليق", + "updateServiceRequest" : "تعديل طلب الخدمة" } \ No newline at end of file diff --git a/assets/subtitles/en_subtitle.json b/assets/subtitles/en_subtitle.json index 2ce29fb9..3045e66e 100644 --- a/assets/subtitles/en_subtitle.json +++ b/assets/subtitles/en_subtitle.json @@ -188,5 +188,7 @@ "alert": "Alert", "duplicateAlert": "Duplicate Alert", "duplicateAlertMessage": "Are you sure you want to duplicate request?", - "duplicateRequest": "Duplicate Request" + "duplicateRequest": "Duplicate Request", + "comment" : "Comment", + "updateServiceRequest" : "Update Service Request" } \ No newline at end of file diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index a5559bc2..5116f0d6 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -227,6 +227,7 @@ }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -258,6 +259,7 @@ }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 347cd5f4..86b0405c 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -60,5 +60,7 @@ UIViewControllerBasedStatusBarAppearance + UIApplicationSupportsIndirectInputEvents + diff --git a/lib/controllers/api_routes/urls.dart b/lib/controllers/api_routes/urls.dart index 65c8935d..36f430fd 100644 --- a/lib/controllers/api_routes/urls.dart +++ b/lib/controllers/api_routes/urls.dart @@ -14,7 +14,7 @@ class URLs { static String getFileUrl(String file) => file == null || file.isEmpty ? null : "$_host/attachment/$file"; // API Routes - static get login => "$_baseUrl/MobileAuth/Login"; // post + static get login => "$_baseUrl/MobileAuth/LoginIntegration"; // post static get register => "$_baseUrl/handle/create/user"; // post static get updateProfile => "$_baseUrl/update/user/profile"; // post static get getHospitals => "$_baseUrl/Customer/GetCustomers"; // get @@ -23,7 +23,10 @@ class URLs { static get getModels => "$_baseUrl/ModelDefinition/GetModelDefinitionAsset"; // get ?client=2 // 08051 static get getServiceRequests => "$_baseUrl/CallRequest/GetCallRequests"; // get + static get getServiceRequestById => "$_baseUrl/CallRequest/GetCallRequestById"; // get static get getServiceRequestThrough => "$_baseUrl/Lookups/GetLookup?lookupEnum=603"; // get + static get getServiceLoanAvailability => "$_baseUrl/Lookups/GetLookup?lookupEnum=4"; // get + static get getServiceFirstAction => "$_baseUrl/Lookups/GetLookup?lookupEnum=700"; // get static get getServiceRequestTypes => "$_baseUrl/Lookups/GetLookup?lookupEnum=604"; // get static get getServiceRequestStatus => "$_baseUrl/Lookups/GetLookup?lookupEnum=503"; diff --git a/lib/controllers/providers/api/service_requests_provider.dart b/lib/controllers/providers/api/service_requests_provider.dart index 59062251..bde8b2cf 100644 --- a/lib/controllers/providers/api/service_requests_provider.dart +++ b/lib/controllers/providers/api/service_requests_provider.dart @@ -6,7 +6,6 @@ import 'package:test_sa/controllers/api_routes/api_manager.dart'; import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/issue.dart'; -import 'package:test_sa/models/lookup.dart'; import 'package:test_sa/models/service_report.dart'; import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/models/service_request/service_request_search.dart'; @@ -133,17 +132,42 @@ class ServiceRequestsProvider extends ChangeNotifier { @required ServiceRequest serviceRequest, }) async { var body = { - "callCreatedBy": {"id": user.id, "name": user.userName}, + "id": 0, + "calNo": "", + "callCreatedBy": {"id": user.id, "name": user.userName ?? ""}, "assets": serviceRequest.deviceId == null ? [] : [serviceRequest.deviceId], "requestedDate": DateTime.now().toIso8601String(), "requestedTime": DateTime.now().toIso8601String(), - "client": user.hospital?.id ?? '', + "client": user.clientId, "callComments": serviceRequest.maintenanceIssue, - "attachmentsCallRequest": serviceRequest.devicePhotos.map((e) => {"name": e}).toList(), + if (serviceRequest.devicePhotos.isNotEmpty) "attachmentsCallRequest": serviceRequest.devicePhotos.map((e) => {"name": e}).toList(), "priority": serviceRequest.priority.toMap(), "defectType": serviceRequest.defectType.toMap(), "typeofRequest": serviceRequest.type.toMap(), "requestedThrough": serviceRequest.type.toMap(), + "reviewComment": null, + if (serviceRequest.audio != null) "voiceNote": serviceRequest.audio, + "callSiteContactPerson": [ + { + "id": 0, + // "employeeCode": user.email, + "name": user.userName, + "telephone": user.phoneNumber, + // "job": "", + "email": user.email, + // "land": "", + "contactUserId": user.id, + }, + ], + "noofFollowup": 0, + "status": null, + "callLastSituation": null, + "firstAction": null, + "loanAvailablity": null, + "comments": null, + "firstActionDate": null, + "visitDate": null, + "callReview": null, }; if (serviceRequest.audio != null) { body["voiceNote"] = serviceRequest.audio; @@ -188,16 +212,50 @@ class ServiceRequestsProvider extends ChangeNotifier { Future updateDate({ @required String host, @required User user, - @required String newDate, - @required Lookup employee, @required ServiceRequest request, + DateTime date, }) async { + Map serviceRequest = await getServiceRequestById(requestId: request.id) ?? ""; + final List callSiteContacts = (serviceRequest['callSiteContactPerson'] as List); + final Map callSiteContactPerson = callSiteContacts.isEmpty ? {} : callSiteContacts[0]; + print(callSiteContactPerson); Response response; var body = { - "callCreatedBy": {"id": user.id, "name": user.userName}, + "id": request.id, + "callNo": serviceRequest['callNo'], + "callCreatedBy": serviceRequest['callCreatedBy'], + "requestedDate": date?.toIso8601String() ?? "", + "requestedTime": date?.toIso8601String() ?? "", + "priority": request.priority?.toMap(), + "defectType": request.defectType?.toMap(), + "typeofRequest": request.type?.toMap(), + "requestedThrough": request.requestedThrough?.toMap(), + "voiceNote": request.audio, "assets": request.deviceId == null ? [] : [request.deviceId], - "requestedDate": newDate, - "requestedTime": newDate, + "attachmentsCallRequest": request.devicePhotos?.map((e) => {"name": e})?.toList(), + "callSiteContactPerson": [ + { + "id": callSiteContactPerson['id'] ?? 0, + "employeeCode": callSiteContactPerson['employeeCode'], + "name": callSiteContactPerson['name'] ?? user.userName, + "telephone": callSiteContactPerson['telephone'] ?? user.phoneNumber, + "job": callSiteContactPerson['job'], + "email": callSiteContactPerson['email'] ?? user.email, + "land": callSiteContactPerson['land'], + "contactUserId": user.id, + }, + ], + "callComments": request.maintenanceIssue, + "noofFollowup": 0, + // "status": null, + "callLastSituation": null, + "firstAction": request.firstAction?.toMap(), + "loanAvailablity": request.loanAvailability?.toMap(), + "comments": request.comment, + "firstActionDate": serviceRequest['firstActionDate'], + "visitDate": date?.toIso8601String() ?? "", + "callReview": null, + "reviewComment": null, }; try { response = await ApiManager.instance.put( @@ -206,7 +264,7 @@ class ServiceRequestsProvider extends ChangeNotifier { ); stateCode = response.statusCode; if (response.statusCode >= 200 && response.statusCode < 300) { - request.engineerName = employee.name; + // request.engineerName = employee.name; notifyListeners(); } return response.statusCode; @@ -363,4 +421,29 @@ class ServiceRequestsProvider extends ChangeNotifier { throw (HttpStatusManger.getStatusMessage(status: response.statusCode, subtitle: subtitle)); } } + + Future> getServiceRequestById({@required String requestId}) async { + Response response; + try { + response = await ApiManager.instance.get( + URLs.getServiceRequestById + "?callRequestId=$requestId", + ); + } catch (error) { + print(error); + return {}; + } + + // If the call to the server was successful, parse the JSON. + if (response.statusCode >= 200 && response.statusCode < 300) { + // If the call to the server was successful, parse the JSON. + return { + "callNo": json.decode(response.body)["data"]["callNo"], + "callCreatedBy": json.decode(response.body)["data"]["callCreatedBy"], + "callSiteContactPerson": json.decode(response.body)["data"]["callSiteContactPerson"], + "firstActionDate": json.decode(response.body)["data"]["firstActionDate"], + }; + } else { + return {}; + } + } } diff --git a/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_first_action_provider.dart b/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_first_action_provider.dart new file mode 100644 index 00000000..6c1beb9d --- /dev/null +++ b/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_first_action_provider.dart @@ -0,0 +1,69 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/user.dart'; + +class ServiceFirstActionProvider extends ChangeNotifier { + //reset provider data + void reset() { + _statuses = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int _stateCode; + int get stateCode => _stateCode; + + // contain user data + // when user not login or register _user = null + List _statuses; + List get items => _statuses; + + // when categories in-process _loading = true + // done _loading = true + // failed _loading = false + bool _loading; + bool get isLoading => _loading; + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + Future getData({String host, User user}) async { + if (_loading == true) return -2; + _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get( + URLs.getServiceFirstAction, + ); + _stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + _statuses = categoriesListJson.map((e) => Lookup.fromJson(e)).toList(); + } + _loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_loan_availability_provider.dart b/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_loan_availability_provider.dart new file mode 100644 index 00000000..a4f1594a --- /dev/null +++ b/lib/controllers/providers/api/status_drop_down/service_reqest/service_request_loan_availability_provider.dart @@ -0,0 +1,69 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:test_sa/controllers/api_routes/api_manager.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/models/user.dart'; + +class ServiceLoanAvailabilityProvider extends ChangeNotifier { + //reset provider data + void reset() { + _statuses = null; + _stateCode = null; + } + + // state code of current request to defied error message + // like 400 customer request failed + // 500 service not available + int _stateCode; + int get stateCode => _stateCode; + + // contain user data + // when user not login or register _user = null + List _statuses; + List get items => _statuses; + + // when categories in-process _loading = true + // done _loading = true + // failed _loading = false + bool _loading; + bool get isLoading => _loading; + set isLoading(bool isLoading) { + _loading = isLoading; + notifyListeners(); + } + + /// return -2 if request in progress + /// return -1 if error happen when sending request + /// return state code if request complete may be 200, 404 or 403 + /// for more details check http state manager + /// lib\controllers\http_status_manger\http_status_manger.dart + Future getData({String host, User user}) async { + if (_loading == true) return -2; + _loading = true; + notifyListeners(); + Response response; + try { + response = await ApiManager.instance.get( + URLs.getServiceLoanAvailability, + ); + _stateCode = response.statusCode; + if (response.statusCode >= 200 && response.statusCode < 300) { + // client's request was successfully received + List categoriesListJson = json.decode(response.body)["data"]; + _statuses = categoriesListJson.map((e) => Lookup.fromJson(e)).toList(); + } + _loading = false; + notifyListeners(); + return response.statusCode; + } catch (error) { + _loading = false; + _stateCode = -1; + notifyListeners(); + return -1; + } + } +} diff --git a/lib/controllers/providers/api/user_provider.dart b/lib/controllers/providers/api/user_provider.dart index 918787b0..bce2ce22 100644 --- a/lib/controllers/providers/api/user_provider.dart +++ b/lib/controllers/providers/api/user_provider.dart @@ -98,7 +98,8 @@ class UserProvider extends ChangeNotifier { if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received _user = User.fromJson(jsonDecode(utf8.decode(response.bodyBytes))[0]); - _user.hospital = user.hospital; + _user.clientId = user.clientId; + _user.clientName = user.clientName; notifyListeners(); return response.statusCode; } @@ -123,8 +124,8 @@ class UserProvider extends ChangeNotifier { Map jsonObject = {}; jsonObject["uid"] = user.id; jsonObject["token"] = user.token; - if (user.department.id != _user.department.id) jsonObject["department"] = user.department.id; - if (user.whatsApp != _user.whatsApp) jsonObject["whatsapp"] = user.whatsApp; + if (user.departmentId != _user.departmentId) jsonObject["department"] = user.departmentId; + // if (user.whatsApp != _user.whatsApp) jsonObject["whatsapp"] = user.whatsApp; if (user.phoneNumber != _user.phoneNumber) jsonObject["phone"] = user.phoneNumber; try { response = response = await ApiManager.instance.post( @@ -143,8 +144,10 @@ class UserProvider extends ChangeNotifier { if (response.statusCode >= 200 && response.statusCode < 300) { // client's request was successfully received _user = User.fromJson(jsonDecode(utf8.decode(response.bodyBytes))[0]); - _user.hospital = user.hospital; - _user.department = user.department; + _user.clientId = user.clientId; + _user.clientName = user.clientName; + _user.departmentName = user.departmentName; + _user.departmentId = user.departmentId; notifyListeners(); return response.statusCode; } diff --git a/lib/main.dart b/lib/main.dart index 26805518..60cea674 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,3 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_localizations/flutter_localizations.dart'; -import 'package:provider/provider.dart'; import 'dart:io'; import 'package:firebase_core/firebase_core.dart'; @@ -26,6 +23,8 @@ import 'package:test_sa/controllers/providers/api/status_drop_down/pentry/pentry import 'package:test_sa/controllers/providers/api/status_drop_down/pentry/pentry_visit_status_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_defect_types_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/report/service_report_priority_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/service_reqest/service_request_first_action_provider.dart'; +import 'package:test_sa/controllers/providers/api/status_drop_down/service_reqest/service_request_loan_availability_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/service_reqest/service_request_status_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/service_reqest/service_request_through_provider.dart'; import 'package:test_sa/controllers/providers/api/status_drop_down/service_reqest/service_request_type_provider.dart'; @@ -65,17 +64,16 @@ void main() async { WidgetsFlutterBinding.ensureInitialized(); if (Platform.isIOS) { await Firebase.initializeApp( - options: const FirebaseOptions(apiKey: "AIzaSyACQkSleNwU1jzEKR5ho1uSfZERokwwAbc", appId: "1:973582662416:ios:bc4a8061444c6a08fbc395", messagingSenderId: "973582662416", projectId: "atoms-fb912"), + options: + const FirebaseOptions(apiKey: "AIzaSyACQkSleNwU1jzEKR5ho1uSfZERokwwAbc", appId: "1:973582662416:ios:bc4a8061444c6a08fbc395", messagingSenderId: "973582662416", projectId: "atoms-fb912"), ); } else { await Firebase.initializeApp(); } - runApp( - ChangeNotifierProvider( - create: (_) => SettingProvider(), - child: MyApp(), - ) - ); + runApp(ChangeNotifierProvider( + create: (_) => SettingProvider(), + child: MyApp(), + )); } class MyApp extends StatelessWidget { @@ -115,6 +113,8 @@ class MyApp extends StatelessWidget { ChangeNotifierProvider(create: (_) => ServiceRequestedThroughProvider()), ChangeNotifierProvider(create: (_) => ServiceRequestStatusProvider()), ChangeNotifierProvider(create: (_) => EngineersProvider()), + ChangeNotifierProvider(create: (_) => ServiceLoanAvailabilityProvider()), + ChangeNotifierProvider(create: (_) => ServiceFirstActionProvider()), ], child: GestureDetector( onTap: () { @@ -127,18 +127,12 @@ class MyApp extends StatelessWidget { title: 'ATOMS', debugShowCheckedModeBanner: false, theme: ThemeData( - fontFamily: "Poppins", - //canvasColor: AColors.primaryColor, - scaffoldBackgroundColor: AColors.scaffoldBackgroundColor, - primaryColor: AColors.primaryColor, - indicatorColor: AColors.primaryColor, - colorScheme: const ColorScheme.light( - primary: AColors.primaryColor, - onPrimary: Colors.white, - secondary: AColors.secondaryColor, - onSecondary: Colors.white - ) - ), + fontFamily: "Poppins", + //canvasColor: AColors.primaryColor, + scaffoldBackgroundColor: AColors.scaffoldBackgroundColor, + primaryColor: AColors.primaryColor, + indicatorColor: AColors.primaryColor, + colorScheme: const ColorScheme.light(primary: AColors.primaryColor, onPrimary: Colors.white, secondary: AColors.secondaryColor, onSecondary: Colors.white)), localizationsDelegates: const [ // ... app-specific localization delegate[s] here AppLocalization.delegate, @@ -153,31 +147,28 @@ class MyApp extends StatelessWidget { locale: Locale(_settingProvider.language ?? 'en'), initialRoute: SplashScreen.id, routes: { - SplashScreen.id: (_)=> const SplashScreen(), - LandPage.id: (_)=> const LandPage(), - Login.id: (_)=> Login(), - Register.id: (_)=> Register(), - ProfilePage.id: (_)=> ProfilePage(), - ReportIssuesPage.id: (_)=> const ReportIssuesPage(), - RequestGasRefill.id: (_)=> const RequestGasRefill(), - CreateRequestPage.id: (_)=> CreateRequestPage(), - SingleHospitalPicker.id: (_)=> SingleHospitalPicker(), - SingleDevicePicker.id: (_)=> SingleDevicePicker(), - SingleDepartmentPicker.id: (_)=> SingleDepartmentPicker(), - ServiceRequestsPage.id: (_)=> ServiceRequestsPage(), - NotificationsPage.id: (_)=> NotificationsPage(), - FutureRequestServiceDetails.id: (_)=> FutureRequestServiceDetails(), - PreventiveMaintenanceVisitsPage.id: (_)=> PreventiveMaintenanceVisitsPage(), - RegularVisitsPage.id: (_)=> RegularVisitsPage(), - TrackGasRefillPage.id: (_)=> const TrackGasRefillPage(), - RequestDeviceTransfer.id: (_)=> const RequestDeviceTransfer(), - TrackDeviceTransferPage.id: (_)=> const TrackDeviceTransferPage(), + SplashScreen.id: (_) => const SplashScreen(), + LandPage.id: (_) => const LandPage(), + Login.id: (_) => Login(), + Register.id: (_) => Register(), + ProfilePage.id: (_) => ProfilePage(), + ReportIssuesPage.id: (_) => const ReportIssuesPage(), + RequestGasRefill.id: (_) => const RequestGasRefill(), + CreateRequestPage.id: (_) => const CreateRequestPage(), + SingleHospitalPicker.id: (_) => SingleHospitalPicker(), + SingleDevicePicker.id: (_) => SingleDevicePicker(), + SingleDepartmentPicker.id: (_) => SingleDepartmentPicker(), + ServiceRequestsPage.id: (_) => ServiceRequestsPage(), + NotificationsPage.id: (_) => NotificationsPage(), + FutureRequestServiceDetails.id: (_) => FutureRequestServiceDetails(), + PreventiveMaintenanceVisitsPage.id: (_) => PreventiveMaintenanceVisitsPage(), + RegularVisitsPage.id: (_) => RegularVisitsPage(), + TrackGasRefillPage.id: (_) => const TrackGasRefillPage(), + RequestDeviceTransfer.id: (_) => const RequestDeviceTransfer(), + TrackDeviceTransferPage.id: (_) => const TrackDeviceTransferPage(), }, ), ), ); } } - - - diff --git a/lib/models/service_request/service_request.dart b/lib/models/service_request/service_request.dart index 434f8de7..6ebc748b 100644 --- a/lib/models/service_request/service_request.dart +++ b/lib/models/service_request/service_request.dart @@ -2,7 +2,7 @@ import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/models/device/device.dart'; import 'package:test_sa/models/lookup.dart'; -class ServiceRequest{ +class ServiceRequest { String id; String requestCode; String deviceSerialNumber; @@ -19,6 +19,7 @@ class ServiceRequest{ String audio; int statusValue; String statusLabel; + String comment; bool viewReport; String engineerMobile; @@ -34,6 +35,8 @@ class ServiceRequest{ Lookup defectType; Lookup type; Lookup requestedThrough; + Lookup firstAction; + Lookup loanAvailability; Device device; ServiceRequest({ @@ -53,7 +56,6 @@ class ServiceRequest{ this.deviceId, this.audio, this.engineerName, - this.viewReport = false, this.deviceModel, this.engineerMobile, @@ -69,11 +71,14 @@ class ServiceRequest{ this.type, this.requestedThrough, this.device, + this.comment, + this.loanAvailability, + this.firstAction, }); - factory ServiceRequest.fromJson(Map parsedJson){ + factory ServiceRequest.fromJson(Map parsedJson) { List images = []; - if(parsedJson["attachmentsCallRequest"] is List){ + if (parsedJson["attachmentsCallRequest"] is List) { List list = parsedJson["attachmentsCallRequest"]; images = list.map((e) => URLs.getFileUrl(e["attachmentsCallRequest"])).toList(); } @@ -85,35 +90,33 @@ class ServiceRequest{ deviceId: parsedJson["asset"]["id"], audio: URLs.getFileUrl(parsedJson["voiceNote"] ?? ""), deviceArName: parsedJson["asset"]["modelDefinition"]["assetName"] ?? "", - deviceEnName: parsedJson["asset"]["modelDefinition"]["assetName"] ?? "", + deviceEnName: parsedJson["asset"]["modelDefinition"]["assetName"] ?? "", devicePhotos: images, deviceSerialNumber: parsedJson["asset"]["assetSerialNo"], date: DateTime.tryParse(parsedJson["requestedDate"] ?? "").toString().split(" ").first, maintenanceIssue: parsedJson["comments"], - statusLabel: parsedJson["status"] == null ? null : - parsedJson["status"]["name"], - statusValue: parsedJson["status"] == null ? null : - parsedJson["status"]["value"], - departmentName: parsedJson["asset"]["department"] != null ? - parsedJson["asset"]["department"]["name"] : "", - engineerName: parsedJson["assignedEmployee"] == null ? null : - parsedJson["assignedEmployee"]["name"], + statusLabel: parsedJson["status"] == null ? null : parsedJson["status"]["name"], + statusValue: parsedJson["status"] == null ? null : parsedJson["status"]["value"], + departmentName: parsedJson["asset"]["department"] != null ? parsedJson["asset"]["department"]["name"] : "", + engineerName: parsedJson["assignedEmployee"] == null ? null : parsedJson["assignedEmployee"]["name"], hospitalId: parsedJson["asset"]["site"]["id"], - reportID: parsedJson["workOrder"] != null ? - parsedJson["workOrder"]["workOrderId"] : null, + reportID: parsedJson["workOrder"] != null ? parsedJson["workOrder"]["workOrderId"] : null, viewReport: parsedJson["workOrder"] != null, deviceModel: parsedJson["asset"]["modelDefinition"]["modelName"], - engineerMobile: parsedJson["assignedEmployee"] == null ? null : - parsedJson["assignedEmployee"]["phone"], - faultDescription: parsedJson["workOrder"] != null ? - parsedJson["workOrder"]["faultDescription"] : null, - jobSheetNumber: parsedJson["workOrder"] != null ? - parsedJson["workOrder"]["jobSheetNumber"] :null, + engineerMobile: parsedJson["assignedEmployee"] == null ? null : parsedJson["assignedEmployee"]["phone"], + faultDescription: parsedJson["workOrder"] != null ? parsedJson["workOrder"]["faultDescription"] : null, + jobSheetNumber: parsedJson["workOrder"] != null ? parsedJson["workOrder"]["jobSheetNumber"] : null, visitDate: DateTime.tryParse(parsedJson["visitDate"] ?? "").toString().split(" ").first, nextVisitDate: DateTime.tryParse(parsedJson["nextVisitDate"] ?? ""), - workPerformed: parsedJson["workOrder"] != null ? - parsedJson["workOrder"]["workPerformed"] : null, - device: Device.fromJson(parsedJson["asset"]) + workPerformed: parsedJson["workOrder"] != null ? parsedJson["workOrder"]["workPerformed"] : null, + device: Device.fromJson(parsedJson["asset"]), + comment: parsedJson["reviewComment"], + type: Lookup.fromJson(parsedJson['typeofRequest']), + defectType: Lookup.fromJson(parsedJson['defectType']), + loanAvailability: Lookup.fromJson(parsedJson['loanAvailability']), + firstAction: Lookup.fromJson(parsedJson['firstAction']), + requestedThrough: Lookup.fromJson(parsedJson['requestedThrough']), + priority: Lookup.fromJson(parsedJson['priority']), ); } -} \ No newline at end of file +} diff --git a/lib/models/subtitle.dart b/lib/models/subtitle.dart index a2f212c2..1a05ab65 100644 --- a/lib/models/subtitle.dart +++ b/lib/models/subtitle.dart @@ -1,6 +1,6 @@ import 'package:meta/meta.dart'; -class Subtitle{ +class Subtitle { // http requests status messages String currentlyServiceNotAvailable; String waitUntilYourRequestComplete; @@ -215,8 +215,10 @@ class Subtitle{ String duplicateAlert; String duplicateAlertMessage; String alert; + String comment; + String updateServiceRequest; - void setIssues(List issues){ + void setIssues(List issues) { issues.clear(); issues.add(reason1); issues.add(reason2); @@ -226,6 +228,8 @@ class Subtitle{ } Subtitle({ + @required this.updateServiceRequest, + @required this.comment, @required this.currentlyServiceNotAvailable, @required this.waitUntilYourRequestComplete, @required this.requestCompleteSuccessfully, @@ -278,7 +282,6 @@ class Subtitle{ @required this.titleValidateMessage, @required this.to, @required this.urlNotFound, - @required this.nameExist, @required this.unitRequired, @required this.unite, @@ -384,7 +387,6 @@ class Subtitle{ @required this.pickImage, @required this.requiredImage, @required this.activationAlert, - @required this.callId, @required this.requiredWord, @required this.quantity, @@ -409,8 +411,10 @@ class Subtitle{ @required this.duplicateRequest, }); - factory Subtitle.fromJson(Map parsedJson){ + factory Subtitle.fromJson(Map parsedJson) { return Subtitle( + updateServiceRequest: parsedJson["updateServiceRequest"], + comment: parsedJson["comment"], currentlyServiceNotAvailable: parsedJson["server_error_message"], failedToCompleteRequest: parsedJson["failed_request_message"], requestCompleteSuccessfully: parsedJson["successful_request_message"], @@ -423,7 +427,6 @@ class Subtitle{ signOut: parsedJson["sign_out"], signOutAlert: parsedJson["logout_alert"], language: parsedJson["language"], - name: parsedJson["name"], email: parsedJson["email"], phoneNumber: parsedJson["phone_number"], @@ -437,7 +440,6 @@ class Subtitle{ passwordValidateMessage: parsedJson["password_validate_message"], confirmPasswordValidateMessage: parsedJson["confirm_password_validate_message"], phoneNumberValidateMessage: parsedJson["phone_number_validate_message"], - forgetPasswordWithMark: parsedJson["forget_password_with_mark"], showPassword: parsedJson["show_password"], wrongEmailOrPassword: parsedJson["wrong_email_or_password"], @@ -447,7 +449,6 @@ class Subtitle{ back: parsedJson["back"], search: parsedJson["search"], searchByName: parsedJson["search_by_name"], - address: parsedJson["address"], addressNotFound: parsedJson["address_not_found"], addressValidateMessage: parsedJson["address_validate_message"], @@ -466,7 +467,6 @@ class Subtitle{ titleNotFound: parsedJson["title_not_found"], titleValidateMessage: parsedJson["title_validate_message"], urlNotFound: parsedJson["url_not_found"], - date: parsedJson["date"], status: parsedJson["status"], code: parsedJson["code"], @@ -542,7 +542,6 @@ class Subtitle{ visitDate: parsedJson["visitDate"], whatsApp: parsedJson["whatsApp"], workPerformed: parsedJson["workPerformed"], - actualDate: parsedJson["actualDate"], done: parsedJson["done"], expectDate: parsedJson["expectDate"], @@ -573,7 +572,6 @@ class Subtitle{ requiredImage: parsedJson["requiredImage"], taskStatus: parsedJson["taskStatus"], activationAlert: parsedJson["activationAlert"], - attachImage: parsedJson["attachImage"], callLastSituation: parsedJson["callLastSituation"], customer: parsedJson["customer"], @@ -592,12 +590,10 @@ class Subtitle{ requiredWord: parsedJson["requiredWord"], serviceType: parsedJson["serviceType"], workPreformed: parsedJson["workPreformed"], - alert: parsedJson["alert"], duplicateAlert: parsedJson["duplicateAlert"], duplicateAlertMessage: parsedJson["duplicateAlertMessage"], duplicateRequest: parsedJson["duplicateRequest"], ); } - -} \ No newline at end of file +} diff --git a/lib/models/user.dart b/lib/models/user.dart index 05a1f3cc..7cfcb713 100644 --- a/lib/models/user.dart +++ b/lib/models/user.dart @@ -1,108 +1,219 @@ import 'package:test_sa/controllers/notification/firebase_notification_manger.dart'; -import 'package:test_sa/models/department.dart'; import 'package:test_sa/models/enums/user_types.dart'; -import 'package:test_sa/models/hospital.dart'; class User { + int clientId; + String clientName; + int departmentId; + String departmentName; + String message; + String username; + String userID; + String email; + String password; + String token; + dynamic roles; + List userRoles; + String tokenlife; + bool isAuthenticated; + bool hasError; + String profilePhotoName; String id; String userName; - String password; - String email; - Hospital hospital; - Department department; - UsersTypes type; + String normalizedUserName; + String normalizedEmail; + bool emailConfirmed; + dynamic passwordHash; + String securityStamp; + String concurrencyStamp; String phoneNumber; - String whatsApp; - String token; - bool isActive; - DateTime tokenLife; + bool phoneNumberConfirmed; + bool twoFactorEnabled; + dynamic lockoutEnd; + bool lockoutEnabled; + int accessFailedCount; - User( - {this.id, - this.userName = "", - this.email = "", - this.password = "", - this.phoneNumber = "", - this.hospital, - this.department, - this.type, - this.whatsApp, - this.token, - this.tokenLife, - this.isActive = false}); + User({ + this.clientId, + this.clientName, + this.departmentId, + this.departmentName, + this.message, + this.username, + this.userID, + this.email, + this.password, + this.token, + this.roles, + this.userRoles, + this.tokenlife, + this.isAuthenticated, + this.hasError, + this.profilePhotoName, + this.id, + this.userName, + this.normalizedUserName, + this.normalizedEmail, + this.emailConfirmed, + this.passwordHash, + this.securityStamp, + this.concurrencyStamp, + this.phoneNumber, + this.phoneNumberConfirmed, + this.twoFactorEnabled, + this.lockoutEnd, + this.lockoutEnabled, + this.accessFailedCount, + }); Future> toLoginJson() async { if (FirebaseNotificationManger.token == null) await FirebaseNotificationManger.getToken(); return { "username": userName, "password": password, - "firebase_token": FirebaseNotificationManger?.token ?? "", + "fireBaseToken": FirebaseNotificationManger?.token ?? "", }; } + UsersTypes get type { + switch (userRoles.first.name) { + case "Engineer": + return UsersTypes.engineer; + case "Hospital": + return UsersTypes.normal_user; + default: + return null; + } + } + Map toUpdateProfileJson() { Map jsonObject = {}; - if (department?.id != null) jsonObject["department"] = department.id; - if (whatsApp != null && whatsApp.isNotEmpty) jsonObject["whatsapp"] = whatsApp; - if (phoneNumber != null && phoneNumber.isNotEmpty) jsonObject["phone"] = phoneNumber; + // if (departmentId != null) jsonObject["department"] = departmentId; + // if (whatsApp != null && whatsApp.isNotEmpty) jsonObject["whatsapp"] = whatsApp; + // if (phoneNumber != null && phoneNumber.isNotEmpty) jsonObject["phone"] = phoneNumber; return jsonObject; } Future> toRegisterJson() async { - if (FirebaseNotificationManger.token == null) await FirebaseNotificationManger.getToken(); + // if (FirebaseNotificationManger.token == null) await FirebaseNotificationManger.getToken(); return { - "username": userName, - "email": email, - "whatsapp": whatsApp, - "client": hospital.id, - "department": department?.id, - "phone": phoneNumber, - "pass": password, - "firebase_token": FirebaseNotificationManger?.token ?? "", + // "username": userName, + // "email": email, + // "whatsapp": whatsApp, + // "client": hospital.id, + // "department": department?.id, + // "phone": phoneNumber, + // "pass": password, + // "firebase_token": FirebaseNotificationManger?.token ?? "", }; } Map toJson() { - return { - "userID": id, - "username": userName, - "email": email, - "token": token, - "phoneNumber": phoneNumber, - "whatsapp": whatsApp, - "client_id": hospital?.id, - "client_name": hospital?.name, - "department_id": department?.id, - "department_name": department?.name, - //"password":password, - "tokenlife": tokenLife.toIso8601String(), - "active": isActive, - "userRoles": type == UsersTypes.engineer ? "value: R-6" : "value: R-5", - // "token":token, pass is token - }; + final map = {}; + map['client_id'] = clientId; + map['client_name'] = clientName; + map['department_id'] = departmentId; + map['department_name'] = departmentName; + map['message'] = message; + map['username'] = username; + map['userID'] = userID; + map['email'] = email; + map['password'] = password; + map['token'] = token; + map['roles'] = roles; + if (userRoles != null) { + map['userRoles'] = userRoles.map((v) => v.toJson()).toList(); + } + map['tokenlife'] = tokenlife; + map['isAuthenticated'] = isAuthenticated; + map['hasError'] = hasError; + map['profilePhotoName'] = profilePhotoName; + map['id'] = id; + map['userName'] = userName; + map['normalizedUserName'] = normalizedUserName; + map['normalizedEmail'] = normalizedEmail; + map['emailConfirmed'] = emailConfirmed; + map['passwordHash'] = passwordHash; + map['securityStamp'] = securityStamp; + map['concurrencyStamp'] = concurrencyStamp; + map['phoneNumber'] = phoneNumber; + map['phoneNumberConfirmed'] = phoneNumberConfirmed; + map['twoFactorEnabled'] = twoFactorEnabled; + map['lockoutEnd'] = lockoutEnd; + map['lockoutEnabled'] = lockoutEnabled; + map['accessFailedCount'] = accessFailedCount; + return map; } - factory User.fromJson(Map parsedJson) { - UsersTypes type; - if (parsedJson["userRoles"].toString().contains("value: R-4") || parsedJson["userRoles"].toString().contains("value: R-5") || parsedJson["userRoles"].toString().contains("value: R-7")) { - type = UsersTypes.normal_user; - } else { - type = UsersTypes.engineer; + User.fromJson(dynamic json) { + clientId = json['client_id']; + clientName = json['client_name']; + departmentId = json['department_id']; + departmentName = json['department_name']; + message = json['message']; + username = json['username']; + userID = json['userID']; + email = json['email']; + password = json['password']; + token = json['token']; + roles = json['roles']; + if (json['userRoles'] != null) { + userRoles = []; + json['userRoles'].forEach((v) { + userRoles.add(UserRoles.fromJson(v)); + }); } - return User( - id: parsedJson["userID"], - userName: parsedJson["username"], - email: parsedJson["email"], - hospital: Hospital(id: parsedJson["client_id"], name: parsedJson["client_name"]), - department: Department( - id: parsedJson["department_id"], - name: parsedJson["department_name"], - ), - phoneNumber: parsedJson["phoneNumber"], - whatsApp: parsedJson["phoneNumber"], - token: parsedJson["token"], - isActive: parsedJson["isAuthenticated"], - tokenLife: DateTime.tryParse(parsedJson["tokenlife"] ?? ""), - type: type); + tokenlife = json['tokenlife']; + isAuthenticated = json['isAuthenticated']; + hasError = json['hasError']; + profilePhotoName = json['profilePhotoName']; + id = json['id']; + userName = json['userName']; + normalizedUserName = json['normalizedUserName']; + normalizedEmail = json['normalizedEmail']; + emailConfirmed = json['emailConfirmed']; + passwordHash = json['passwordHash']; + securityStamp = json['securityStamp']; + concurrencyStamp = json['concurrencyStamp']; + phoneNumber = json['phoneNumber']; + phoneNumberConfirmed = json['phoneNumberConfirmed']; + twoFactorEnabled = json['twoFactorEnabled']; + lockoutEnd = json['lockoutEnd']; + lockoutEnabled = json['lockoutEnabled']; + accessFailedCount = json['accessFailedCount']; + } +} + +class UserRoles { + UserRoles({ + this.id, + this.name, + this.value, + }); + + UserRoles.fromJson(dynamic json) { + id = json['id']; + name = json['name']; + value = json['value']; + } + String id; + String name; + String value; + UserRoles copyWith({ + String id, + String name, + String value, + }) => + UserRoles( + id: id ?? this.id, + name: name ?? this.name, + value: value ?? this.value, + ); + Map toJson() { + final map = {}; + map['id'] = id; + map['name'] = name; + map['value'] = value; + return map; } } diff --git a/lib/views/pages/device_transfer/request_device_transfer.dart b/lib/views/pages/device_transfer/request_device_transfer.dart index b3beb23f..9deba1eb 100644 --- a/lib/views/pages/device_transfer/request_device_transfer.dart +++ b/lib/views/pages/device_transfer/request_device_transfer.dart @@ -35,7 +35,7 @@ class _RequestDeviceTransferState extends State { SettingProvider _settingProvider; DeviceTransferProvider _deviceTransferProvider; final TextEditingController _requestedQuantityController = TextEditingController(); - final DeviceTransfer _formModel = DeviceTransfer(receiver: DeviceTransferInfo(),sender: DeviceTransferInfo()); + final DeviceTransfer _formModel = DeviceTransfer(receiver: DeviceTransferInfo(), sender: DeviceTransferInfo()); final GlobalKey _formKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); @@ -59,7 +59,7 @@ class _RequestDeviceTransferState extends State { _isLoading = true; setState(() {}); - _formModel.sender?.client?.id = _userProvider.user?.hospital?.id; + _formModel.sender?.client?.id = _userProvider.user?.clientId; int status = await _deviceTransferProvider.createRequest( user: _userProvider.user, host: _settingProvider.host, diff --git a/lib/views/pages/login.dart b/lib/views/pages/login.dart index 3bd061b0..65585b85 100644 --- a/lib/views/pages/login.dart +++ b/lib/views/pages/login.dart @@ -113,7 +113,7 @@ class _LoginState extends State { user: _user, host: _settingProvider.host, ); - if (status >= 200 && status < 300 && _userProvider.user?.userName != null) { + if (status >= 200 && status < 300) { _settingProvider.setUser(_userProvider.user); // if (_userProvider.user.isActive) Navigator.of(context).pushNamed(LandPage.id); diff --git a/lib/views/pages/register.dart b/lib/views/pages/register.dart index 22cd7d91..ab370de9 100644 --- a/lib/views/pages/register.dart +++ b/lib/views/pages/register.dart @@ -1,12 +1,13 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/controllers/validator/validator.dart'; +import 'package:test_sa/models/department.dart'; +import 'package:test_sa/models/hospital.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/models/user.dart'; import 'package:test_sa/views/widgets/app_text_form_field.dart'; @@ -123,17 +124,19 @@ class _RegisterState extends State { ), const SizedBox(height: 12), HospitalButton( - hospital: _user.hospital, + hospital: Hospital(id: _user.clientId, name: _user.clientName), onHospitalPick: (hospital) { - _user.hospital = hospital; + _user.clientId = hospital.id; + _user.clientName = hospital.name; setState(() {}); }, ), const SizedBox(height: 12), DepartmentButton( - department: _user.department, + department: Department(id: _user.departmentId, name: _user.departmentName), onDepartmentPick: (department) { - _user.department = department; + _user.departmentId = department.id; + _user.departmentName = department.name; setState(() {}); }, ), @@ -150,31 +153,31 @@ class _RegisterState extends State { }, ), SizedBox(height: 8), - ATextFormField( - initialValue: _user.whatsApp, - hintText: _subtitle.whatsApp, - style: Theme.of(context).textTheme.headline6, - prefixIconData: FontAwesomeIcons.whatsapp, - prefixIconSize: 36, - validator: (value) => Validator.isPhoneNumber(value) ? null : _subtitle.phoneNumberValidateMessage, - textInputType: TextInputType.phone, - onSaved: (value) { - _user.whatsApp = value; - }, - ), + // ATextFormField( + // initialValue: _user.whatsApp, + // hintText: _subtitle.whatsApp, + // style: Theme.of(context).textTheme.headline6, + // prefixIconData: FontAwesomeIcons.whatsapp, + // prefixIconSize: 36, + // validator: (value) => Validator.isPhoneNumber(value) ? null : _subtitle.phoneNumberValidateMessage, + // textInputType: TextInputType.phone, + // onSaved: (value) { + // _user.whatsApp = value; + // }, + // ), const SizedBox(height: 12), AButton( text: _subtitle.signUp, onPressed: () async { if (!_formKey.currentState.validate()) return; _formKey.currentState.save(); - if (_user.hospital == null) { + if (_user.clientId == null) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(_subtitle.hospitalRequired), )); return; } - if (_user.department == null) { + if (_user.departmentId == null) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(_subtitle.unitRequired), )); diff --git a/lib/views/pages/splash_screen.dart b/lib/views/pages/splash_screen.dart index bd7a770f..e28c09de 100644 --- a/lib/views/pages/splash_screen.dart +++ b/lib/views/pages/splash_screen.dart @@ -22,12 +22,11 @@ class SplashScreen extends StatefulWidget { } class _SplashScreenState extends State { - SettingProvider _settingProvider; UserProvider _userProvider; - _goToUserScreen(User user){ - if(user.tokenLife != null && user.tokenLife.isAfter(DateTime.now())){ + _goToUserScreen(User user) { + if (user.tokenlife != null && (DateTime.tryParse(user.tokenlife)?.isAfter(DateTime.now()) ?? false)) { _userProvider.user = user; // Navigator.of(context).pushNamed(Login.id); Navigator.of(context).pushNamed(LandPage.id); @@ -38,38 +37,30 @@ class _SplashScreenState extends State { void initState() { Firebase.initializeApp(); - NotificationManger.initialisation( - (notificationDetails) { - AppNotification notification = AppNotification.fromJson(json.decode(notificationDetails.payload)); - if(notification.path == null || notification.path.isEmpty) - return; - Navigator.pushNamed( - context, - notification.path, - arguments: notification.requestId - ); - } - , (id, title, body, payload) async { - }); + NotificationManger.initialisation((notificationDetails) { + AppNotification notification = AppNotification.fromJson(json.decode(notificationDetails.payload)); + if (notification.path == null || notification.path.isEmpty) return; + Navigator.pushNamed(context, notification.path, arguments: notification.requestId); + }, (id, title, body, payload) async {}); super.initState(); } @override Widget build(BuildContext context) { - _settingProvider = Provider.of(context,listen: false); - _userProvider = Provider.of(context,listen: false); + _settingProvider = Provider.of(context, listen: false); + _userProvider = Provider.of(context, listen: false); return Scaffold( backgroundColor: Colors.white, body: Center( child: SizedBox( - width: MediaQuery.of(context).size.width/1.1, - child: FlareActor( + width: MediaQuery.of(context).size.width / 1.1, + child: FlareActor( "assets/rives/atoms_splash.flr", fit: BoxFit.contain, animation: "splash", callback: (animation) async { Navigator.of(context).pushNamed(Login.id); - if(_settingProvider.isLoaded && _settingProvider.user != null){ + if (_settingProvider.isLoaded && _settingProvider.user != null) { _goToUserScreen(_settingProvider.user); } }, diff --git a/lib/views/pages/user/notifications/notifications_page.dart b/lib/views/pages/user/notifications/notifications_page.dart index a0e85259..bab082e3 100644 --- a/lib/views/pages/user/notifications/notifications_page.dart +++ b/lib/views/pages/user/notifications/notifications_page.dart @@ -9,14 +9,14 @@ import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/pages/user/notifications/notifications_list.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; + class NotificationsPage extends StatefulWidget { static final String id = "/notifications"; @override _NotificationsPageState createState() => _NotificationsPageState(); } -class _NotificationsPageState extends State - with TickerProviderStateMixin{ +class _NotificationsPageState extends State with TickerProviderStateMixin { NotificationsProvider _notificationsProvider; UserProvider _userProvider; SettingProvider _settingProvider; @@ -36,9 +36,9 @@ class _NotificationsPageState extends State onRefresh: () async { _notificationsProvider.reset(); await _notificationsProvider.getNotifications( - user: _userProvider.user, - host: _settingProvider.host, - hospitalId: _userProvider.user.hospital.id, + user: _userProvider.user, + host: _settingProvider.host, + hospitalId: _userProvider.user.clientId, ); }, child: Stack( @@ -46,8 +46,8 @@ class _NotificationsPageState extends State Column( children: [ Container( - color:AColors.primaryColor, - padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), + color: AColors.primaryColor, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), child: Column( children: [ Row( @@ -57,17 +57,15 @@ class _NotificationsPageState extends State child: Center( child: Text( _subtitle.notifications, - style: Theme.of(context).textTheme.headline6.copyWith( - color: AColors.white, - fontStyle: FontStyle.italic - ), + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), ), ), ), - SizedBox(width: 48,) + SizedBox( + width: 48, + ) ], ), - ], ), ), @@ -78,7 +76,7 @@ class _NotificationsPageState extends State await _notificationsProvider.getNotifications( user: _userProvider.user, host: _settingProvider.host, - hospitalId: _userProvider.user.hospital.id, + hospitalId: _userProvider.user.clientId, ); }, notifications: _notificationsProvider.notifications, @@ -86,7 +84,6 @@ class _NotificationsPageState extends State ), ], ), - ], ), ), diff --git a/lib/views/pages/user/profile_page.dart b/lib/views/pages/user/profile_page.dart index 0b3757a0..f5bb5c2c 100644 --- a/lib/views/pages/user/profile_page.dart +++ b/lib/views/pages/user/profile_page.dart @@ -1,11 +1,12 @@ import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/controllers/api_routes/http_status_manger.dart'; import 'package:test_sa/controllers/localization/localization.dart'; import 'package:test_sa/controllers/providers/api/user_provider.dart'; import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/controllers/validator/validator.dart'; +import 'package:test_sa/models/department.dart'; +import 'package:test_sa/models/hospital.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/models/user.dart'; import 'package:test_sa/views/app_style/colors.dart'; @@ -16,6 +17,7 @@ import 'package:test_sa/views/widgets/buttons/app_button.dart'; import 'package:test_sa/views/widgets/departments/department_button.dart'; import 'package:test_sa/views/widgets/hospitals/hospital_button.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; + class ProfilePage extends StatefulWidget { static final String id = "/user/profile"; @override @@ -38,13 +40,13 @@ class _ProfilePageState extends State { _width = MediaQuery.of(context).size.width; _height = MediaQuery.of(context).size.height; Subtitle _subtitle = AppLocalization.of(context).subtitle; - if(_firstTime){ + if (_firstTime) { _user = User.fromJson(_userProvider.user.toJson()); _firstTime = false; } return Scaffold( key: _scaffoldKey, - body:LoadingManager( + body: LoadingManager( isLoading: _userProvider.isLoading, isFailedLoading: false, stateCode: 200, @@ -60,23 +62,19 @@ class _ProfilePageState extends State { Hero( tag: "logo", child: Image( - height: _height/4, + height: _height / 4, image: AssetImage("assets/images/logo.png"), ), ), Container( - padding: EdgeInsets.symmetric(horizontal: 16,vertical: 16), + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16), margin: EdgeInsets.symmetric(horizontal: 16), - decoration: BoxDecoration( - color: AColors.primaryColor, - borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), - boxShadow: [ - BoxShadow( - color: AColors.grey, - offset: Offset(0,-1), - ) - ] - ), + decoration: BoxDecoration(color: AColors.primaryColor, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [ + BoxShadow( + color: AColors.grey, + offset: Offset(0, -1), + ) + ]), child: Column( children: [ ATextFormField( @@ -85,13 +83,14 @@ class _ProfilePageState extends State { enable: false, prefixIconData: Icons.account_circle, style: Theme.of(context).textTheme.headline6, - validator: (value) => Validator.hasValue(value) - ? null : _subtitle.nameValidateMessage, - onSaved: (value){ + validator: (value) => Validator.hasValue(value) ? null : _subtitle.nameValidateMessage, + onSaved: (value) { _user.userName = value; }, ), - SizedBox(height: 8,), + SizedBox( + height: 8, + ), ATextFormField( initialValue: _user.email, hintText: _subtitle.email, @@ -99,110 +98,108 @@ class _ProfilePageState extends State { prefixIconData: Icons.email, textInputType: TextInputType.emailAddress, style: Theme.of(context).textTheme.headline6, - validator: (value) => Validator.isEmail(value) - ? null : _subtitle.emailValidateMessage, - onSaved: (value){ + validator: (value) => Validator.isEmail(value) ? null : _subtitle.emailValidateMessage, + onSaved: (value) { _user.email = value; }, ), - SizedBox(height: 8,), + SizedBox( + height: 8, + ), AbsorbPointer( child: HospitalButton( - hospital: _user.hospital, - onHospitalPick: (hospital){ - _user.hospital = hospital; + hospital: Hospital(name: _user.clientName, id: _user.clientId), + onHospitalPick: (hospital) { + _user.clientName = hospital.name; + _user.clientId = hospital.id; setState(() {}); }, ), ), - SizedBox(height: 8,), + SizedBox( + height: 8, + ), DepartmentButton( - department: _user.department, - onDepartmentPick: (department){ - _user.department = department; + department: Department(name: _user.departmentName, id: _user.departmentId), + onDepartmentPick: (department) { + _user.departmentName = department.name; + _user.departmentId = department.id; setState(() {}); }, ), - SizedBox(height: 8,), + SizedBox( + height: 8, + ), ATextFormField( initialValue: _user.phoneNumber, hintText: _subtitle.phoneNumber, style: Theme.of(context).textTheme.headline6, prefixIconData: Icons.phone_android, - validator: (value) => - Validator.isPhoneNumber(value) ? null : _subtitle.phoneNumberValidateMessage, + validator: (value) => Validator.isPhoneNumber(value) ? null : _subtitle.phoneNumberValidateMessage, textInputType: TextInputType.phone, - onSaved: (value){ + onSaved: (value) { _user.phoneNumber = value; }, ), - SizedBox(height: 8,), - ATextFormField( - initialValue: _user.whatsApp, - hintText: _subtitle.whatsApp, - style: Theme.of(context).textTheme.headline6, - prefixIconData: FontAwesomeIcons.whatsapp, - prefixIconSize: 36, - validator: (value) => - Validator.isPhoneNumber(value) ? null : _subtitle.phoneNumberValidateMessage, - textInputType: TextInputType.phone, - onSaved: (value){ - _user.whatsApp = value; - }, + SizedBox( + height: 8, ), + // ATextFormField( + // initialValue: _user.whatsApp, + // hintText: _subtitle.whatsApp, + // style: Theme.of(context).textTheme.headline6, + // prefixIconData: FontAwesomeIcons.whatsapp, + // prefixIconSize: 36, + // validator: (value) => + // Validator.isPhoneNumber(value) ? null : _subtitle.phoneNumberValidateMessage, + // textInputType: TextInputType.phone, + // onSaved: (value){ + // _user.whatsApp = value; + // }, + // ), ], ), ), - SizedBox(height: 16,), + SizedBox( + height: 16, + ), Center( child: SizedBox( height: _width / 8, - width: _width/1.2, + width: _width / 1.2, child: AButton( text: _subtitle.update, onPressed: () async { - if(!_formKey.currentState.validate()) - return; + if (!_formKey.currentState.validate()) return; _formKey.currentState.save(); - if(_user.department?.id == null){ - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - _subtitle.unitRequired - ), - ) - ); + if (_user.departmentId == null) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(_subtitle.unitRequired), + )); return; } int status = await _userProvider.updateProfile( user: _user, host: _settingProvider.host, ); - if(status >= 200 && status < 300){ + if (status >= 200 && status < 300) { _settingProvider.setUser(_userProvider.user); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - _subtitle.requestCompleteSuccessfully - ), - ) - ); - }else{ - String errorMessage = HttpStatusManger.getStatusMessage( - status: status, subtitle: _subtitle); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - errorMessage - ), - ) - ); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(_subtitle.requestCompleteSuccessfully), + )); + } else { + String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(errorMessage), + )); } }, ), ), ), - SizedBox(height: 32,), + SizedBox( + height: 32, + ), ], ), ), diff --git a/lib/views/pages/user/requests/create_request.dart b/lib/views/pages/user/requests/create_request.dart index b5c71478..fb676de4 100644 --- a/lib/views/pages/user/requests/create_request.dart +++ b/lib/views/pages/user/requests/create_request.dart @@ -31,36 +31,53 @@ import 'package:test_sa/views/widgets/status/service_request/service_request_pri import 'package:test_sa/views/widgets/status/service_request/service_request_through_mune.dart'; import 'package:test_sa/views/widgets/status/service_request/service_request_types_mune.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; + +import '../../../widgets/date_and_time/date_picker.dart'; +import '../../../widgets/status/service_request/service_request_first_action.dart'; +import '../../../widgets/status/service_request/service_request_loan_availability.dart'; + class CreateRequestPage extends StatefulWidget { - static final String id = "/create-request"; + static const String id = "/create-request"; + final ServiceRequest serviceRequest; + const CreateRequestPage({this.serviceRequest, Key key}) : super(key: key); @override - _CreateRequestPageState createState() => _CreateRequestPageState(); + CreateRequestPageState createState() => CreateRequestPageState(); } -class _CreateRequestPageState extends State { +class CreateRequestPageState extends State { double _height; UserProvider _userProvider; SettingProvider _settingProvider; ServiceRequestsProvider _serviceRequestsProvider; - ServiceRequest _serviceRequest = ServiceRequest(); - List _deviceImages = []; + ServiceRequest _serviceRequest; + final List _deviceImages = []; bool _isLoading = false; Device _device; Subtitle _subtitle; final GlobalKey _formKey = GlobalKey(); final GlobalKey _scaffoldKey = GlobalKey(); - TextEditingController _controller; + TextEditingController _maintenanceController, _commentController; + DateTime _dateTime; @override void initState() { - _controller = TextEditingController(); + _maintenanceController = TextEditingController(); + _commentController = TextEditingController(); + if (widget.serviceRequest != null) { + _serviceRequest = widget.serviceRequest; + _device = _serviceRequest.device; + _deviceImages.addAll(_serviceRequest.devicePhotos.map((e) => File(e)).toList()); + } else { + _serviceRequest = ServiceRequest(); + } super.initState(); } @override void dispose() { - _controller.dispose(); + _maintenanceController.dispose(); + _commentController.dispose(); super.dispose(); } @@ -86,21 +103,19 @@ class _CreateRequestPageState extends State { ListView( children: [ //AppNameBar(), - SizedBox( - height: 16, - ), + const SizedBox(height: 16), Hero( tag: "logo", child: Image( height: _height / 6, - image: AssetImage("assets/images/logo.png"), + image: const AssetImage("assets/images/logo.png"), ), ), Center( child: Padding( padding: const EdgeInsets.all(8.0), child: Text( - _subtitle.newServiceRequest, + widget.serviceRequest == null ? _subtitle.newServiceRequest : _subtitle.updateServiceRequest, style: Theme.of(context).textTheme.headline5.copyWith(color: AColors.cyan, fontWeight: FontWeight.w600), ), ), @@ -109,21 +124,21 @@ class _CreateRequestPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ 12.height, - _userProvider.user.hospital == null - ? SizedBox.shrink() + _userProvider.user.clientId == null + ? const SizedBox.shrink() : ATextFormField( enable: false, - initialValue: _userProvider.user.hospital?.name ?? _subtitle.noHospitalFound, + initialValue: _userProvider.user.clientName ?? _subtitle.noHospitalFound, hintText: _subtitle.hospital, prefixIconData: FontAwesomeIcons.hospital, style: Theme.of(context).textTheme.subtitle1, ), 12.height, - _userProvider.user.department == null - ? SizedBox.shrink() + _userProvider.user.departmentId == null + ? const SizedBox.shrink() : ATextFormField( enable: false, - initialValue: _userProvider.user.department?.name ?? _subtitle.noUniteFound, + initialValue: _userProvider.user.departmentName ?? _subtitle.noUniteFound, hintText: _subtitle.unite, prefixIconData: FontAwesomeIcons.hospitalUser, style: Theme.of(context).textTheme.subtitle1, @@ -136,53 +151,105 @@ class _CreateRequestPageState extends State { setState(() {}); }, ), - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), const ASubTitle("Priority"), - const SizedBox(height: 4,), + const SizedBox( + height: 4, + ), ServiceRequestPriorityMenu( initialValue: _serviceRequest.priority, - onSelect: (status){ + onSelect: (status) { _serviceRequest.priority = status; }, ), - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), const ASubTitle("Defect Type"), - const SizedBox(height: 4,), + const SizedBox( + height: 4, + ), ServiceRequestDefectTypesMenu( initialValue: _serviceRequest.defectType, - onSelect: (status){ + onSelect: (status) { _serviceRequest.defectType = status; }, ), 12.height, - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), const ASubTitle("Type"), - const SizedBox(height: 4,), + const SizedBox( + height: 4, + ), ServiceRequestTypesMenu( initialValue: _serviceRequest.type, - onSelect: (status){ + onSelect: (status) { _serviceRequest.type = status; }, ), - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), const ASubTitle("Through"), - const SizedBox(height: 4,), + const SizedBox( + height: 4, + ), ServiceRequestedThroughMenu( - initialValue: const Lookup(name: "App",value: 3), - onSelect: (status){ + initialValue: const Lookup(name: "App", value: 375), + onSelect: (status) { _serviceRequest.requestedThrough = status; }, ), + if (widget.serviceRequest != null) 12.height, + if (widget.serviceRequest != null) const ASubTitle("First Action"), + const SizedBox( + height: 4, + ), + if (widget.serviceRequest != null) + ServiceRequestedFirstAction( + initialValue: _serviceRequest.firstAction, + onSelect: (status) { + _dateTime = null; + _serviceRequest.firstAction = status; + _serviceRequestsProvider.notifyListeners(); + }, + ), + if (_serviceRequest.firstAction != null) 12.height, + if (_serviceRequest.firstAction != null) + ADatePicker( + date: _dateTime, + from: DateTime.now(), + onDatePicker: (date) { + _dateTime = date; + setState(() {}); + }, + ), + if (widget.serviceRequest != null) 12.height, + if (widget.serviceRequest != null) const ASubTitle("Loan Availability"), + const SizedBox( + height: 4, + ), + if (widget.serviceRequest != null) + ServiceRequestedLoanAvailability( + initialValue: _serviceRequest.loanAvailability, + onSelect: (status) { + _serviceRequest.loanAvailability = status; + }, + ), 12.height, MultiImagesPicker( label: _subtitle.deviceImages, images: _deviceImages, ), 12.height, - SpeechToTextButton(controller: _controller), + SpeechToTextButton(controller: _maintenanceController), 12.height, ATextFormField( - controller: _controller, + controller: _maintenanceController, initialValue: _serviceRequest.maintenanceIssue, hintText: _subtitle.maintenanceIssue, prefixIconData: FontAwesomeIcons.triangleExclamation, @@ -198,29 +265,57 @@ class _CreateRequestPageState extends State { _serviceRequest.audio = audio; }), 12.height, + if (widget.serviceRequest != null) + ATextFormField( + controller: _commentController, + initialValue: _serviceRequest.comment, + hintText: _subtitle.comment, + style: Theme.of(context).textTheme.titleMedium, + textInputType: TextInputType.multiline, + onSaved: (value) { + _serviceRequest.comment = value; + }, + ), ], ).paddingOnly(left: 20, right: 20), Padding( padding: const EdgeInsets.all(20.0), child: AButton( - text: _subtitle.submit, + text: widget.serviceRequest == null ? _subtitle.submit : _subtitle.update, onPressed: () async { if (!_formKey.currentState.validate()) return; + if (_device?.id == null) { + Fluttertoast.showToast(msg: _subtitle.pickDevice); + return; + } + if (_serviceRequest.firstAction != null && _dateTime == null) { + Fluttertoast.showToast(msg: _subtitle.noDateFound); + return; + } _formKey.currentState.save(); - _serviceRequest.deviceId = _device?.id ?? ""; + _serviceRequest.deviceId = _device?.id; _isLoading = true; setState(() {}); - _serviceRequest.devicePhotos = _deviceImages.map( - (e) => "${e.path.split("/").last}|${base64Encode(e.readAsBytesSync())}").toList(); - if(_serviceRequest.audio != null){ + _serviceRequest.devicePhotos = _deviceImages.map((e) => "${e.path.split("/").last}|${base64Encode(e.readAsBytesSync())}").toList(); + if (_serviceRequest.audio != null) { final file = File(_serviceRequest.audio); _serviceRequest.audio = "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}"; } - int status = await _serviceRequestsProvider.createRequest( - user: _userProvider.user, - host: _settingProvider.host, - serviceRequest: _serviceRequest, - ); + int status = 0; + if (widget.serviceRequest == null) { + status = await _serviceRequestsProvider.createRequest( + user: _userProvider.user, + host: _settingProvider.host, + serviceRequest: _serviceRequest, + ); + } else { + status = await _serviceRequestsProvider.updateDate( + user: _userProvider.user, + host: _settingProvider.host, + request: _serviceRequest, + date: _dateTime, + ); + } _isLoading = false; setState(() {}); if (status >= 200 && status < 300) { @@ -239,7 +334,7 @@ class _CreateRequestPageState extends State { ), ], ), - ABackButton(), + const ABackButton(), ], ), ), diff --git a/lib/views/pages/user/requests/request_details.dart b/lib/views/pages/user/requests/request_details.dart index d45692d8..598e8f2b 100644 --- a/lib/views/pages/user/requests/request_details.dart +++ b/lib/views/pages/user/requests/request_details.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; @@ -11,6 +10,7 @@ import 'package:test_sa/models/service_request/service_request.dart'; import 'package:test_sa/models/subtitle.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; +import 'package:test_sa/views/pages/user/requests/create_request.dart'; import 'package:test_sa/views/pages/user/requests/report/create_service_report.dart'; import 'package:test_sa/views/widgets/buttons/app_back_button.dart'; import 'package:test_sa/views/widgets/buttons/app_button.dart'; @@ -19,11 +19,11 @@ import 'package:test_sa/views/widgets/images/images_list.dart'; import 'package:test_sa/views/widgets/loaders/image_loader.dart'; import 'package:test_sa/views/widgets/requests/info_row.dart'; import 'package:test_sa/views/widgets/requests/request_status.dart'; -import 'package:test_sa/views/widgets/requests/service_request_update_dialog.dart'; import 'package:test_sa/views/widgets/sound/sound_player.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; import 'report/future_service_report.dart'; + class RequestDetailsPage extends StatelessWidget { static final String id = "/call-details"; final ServiceRequest serviceRequest; @@ -42,8 +42,8 @@ class RequestDetailsPage extends StatelessWidget { child: Column( children: [ Container( - color:AColors.primaryColor, - padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), + color: AColors.primaryColor, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), child: Row( children: [ ABackButton(), @@ -51,124 +51,133 @@ class RequestDetailsPage extends StatelessWidget { child: Center( child: Text( _subtitle.details, - style: Theme.of(context).textTheme.headline6.copyWith( - color: AColors.white, - fontStyle: FontStyle.italic - ), + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), ), ), ), - _userProvider.user.type == UsersTypes.normal_user ? - // AIconButton( - // iconData: Icons.warning_amber_rounded, - // color: AColors.white, - // buttonSize: 42, - // backgroundColor: AColors.deepOrange, - // onPressed: (){ - // Navigator.of(context).push( - // MaterialPageRoute( - // builder: (_) => ReportIssuesPage(serviceRequest: serviceRequest,) - // ) - // ); - // }, - // ) - const SizedBox(width: 48,) - : AIconButton( - iconData: Icons.edit, - color: AColors.white, - buttonSize: 42, - backgroundColor: AColors.green, - onPressed: () async { - showModalBottomSheet( - context: context, - builder: (context){ - return ServiceRequestsUpdateDialog(request: serviceRequest,); - }); - // DateTime picked = await showDatePicker( - // context: context, - // initialDate: DateTime.now(), - // firstDate: DateTime.now(), - // lastDate: DateTime.now().add(Duration(days: 182)) - // ); - // if(picked == null){return;} - // showDialog( - // context: context, - // barrierDismissible: false, - // builder: (BuildContext context) { - // return CupertinoAlertDialog( - // title: Text(_subtitle.updatingDots), - // content: Center(child: CircularProgressIndicator()), + _userProvider.user.type == UsersTypes.normal_user + ? + // AIconButton( + // iconData: Icons.warning_amber_rounded, + // color: AColors.white, + // buttonSize: 42, + // backgroundColor: AColors.deepOrange, + // onPressed: (){ + // Navigator.of(context).push( + // MaterialPageRoute( + // builder: (_) => ReportIssuesPage(serviceRequest: serviceRequest,) + // ) // ); // }, - // ); - // int status = await _serviceRequestsProvider.updateDate( - // user: _userProvider.user, - // host: _settingProvider.host, - // request: serviceRequest, - // newDate: picked.toString().split(" ").first - // ); - // Navigator.of(context).pop(); - // Fluttertoast.showToast( - // msg: HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle), - // ); - }, - ), - SizedBox(width: 16,) + // ) + const SizedBox( + width: 48, + ) + : AIconButton( + iconData: Icons.edit, + color: AColors.white, + buttonSize: 42, + backgroundColor: AColors.green, + onPressed: () async { + Navigator.of(context).push( + MaterialPageRoute(builder: (_) => CreateRequestPage(serviceRequest: serviceRequest)), + ); + // showModalBottomSheet( + // context: context, + // builder: (context) { + // + // // return ServiceRequestsUpdateDialog(request: serviceRequest,); + // }); + // DateTime picked = await showDatePicker( + // context: context, + // initialDate: DateTime.now(), + // firstDate: DateTime.now(), + // lastDate: DateTime.now().add(Duration(days: 182)) + // ); + // if(picked == null){return;} + // showDialog( + // context: context, + // barrierDismissible: false, + // builder: (BuildContext context) { + // return CupertinoAlertDialog( + // title: Text(_subtitle.updatingDots), + // content: Center(child: CircularProgressIndicator()), + // ); + // }, + // ); + // int status = await _serviceRequestsProvider.updateDate( + // user: _userProvider.user, + // host: _settingProvider.host, + // request: serviceRequest, + // newDate: picked.toString().split(" ").first + // ); + // Navigator.of(context).pop(); + // Fluttertoast.showToast( + // msg: HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle), + // ); + }, + ), + SizedBox( + width: 16, + ) ], ), ), - - serviceRequest.devicePhotos.isEmpty ? SizedBox.shrink(): - Column( - children: [ - SizedBox(height: 8,), - MaterialButton( - padding: EdgeInsets.zero, - onPressed: (){ - Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => Scaffold( - body: InteractiveViewer( - child: Center( - child: ImageLoader( - url: serviceRequest.devicePhotos.first, - boxFit: BoxFit.contain, - ), - ), - ), - ) - ) - ); - }, - child: SizedBox( - height: 140 * AppStyle.getScaleFactor(context), - width: MediaQuery.of(context).size.width, - child: ImageLoader( - url: serviceRequest.devicePhotos.first, - boxFit: BoxFit.cover, - ), - ), - ), - SizedBox(height: 8,), - SizedBox( - height: 60* AppStyle.getScaleFactor(context), - child: ImagesList( - images: serviceRequest.devicePhotos, + serviceRequest.devicePhotos.isEmpty + ? SizedBox.shrink() + : Column( + children: [ + SizedBox( + height: 8, + ), + MaterialButton( + padding: EdgeInsets.zero, + onPressed: () { + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => Scaffold( + body: InteractiveViewer( + child: Center( + child: ImageLoader( + url: serviceRequest.devicePhotos.first, + boxFit: BoxFit.contain, + ), + ), + ), + ))); + }, + child: SizedBox( + height: 140 * AppStyle.getScaleFactor(context), + width: MediaQuery.of(context).size.width, + child: ImageLoader( + url: serviceRequest.devicePhotos.first, + boxFit: BoxFit.cover, + ), + ), + ), + SizedBox( + height: 8, + ), + SizedBox( + height: 60 * AppStyle.getScaleFactor(context), + child: ImagesList( + images: serviceRequest.devicePhotos, + ), + ), + ], ), - ), - ], - ), - - TabBar( - labelColor: AColors.primaryColor, - tabs: [ - Tab(text: _subtitle.general,), - Tab(text: _subtitle.serviceRequestInformation,), + TabBar(labelColor: AColors.primaryColor, tabs: [ + Tab( + text: _subtitle.general, + ), + Tab( + text: _subtitle.serviceRequestInformation, + ), ]), - SizedBox(height: 8,), + SizedBox( + height: 8, + ), Expanded( child: TabBarView( - children: [ ListView( padding: EdgeInsets.symmetric(horizontal: 16), @@ -187,7 +196,7 @@ class RequestDetailsPage extends StatelessWidget { ), RequestInfoRow( title: _subtitle.deviceModel, - info : serviceRequest.deviceModel, + info: serviceRequest.deviceModel, ), RequestInfoRow( title: _subtitle.engineerName, @@ -201,11 +210,12 @@ class RequestDetailsPage extends StatelessWidget { title: _subtitle.date, info: serviceRequest.date, ), - serviceRequest.nextVisitDate == null ? SizedBox.shrink() : - RequestInfoRow( - title: _subtitle.nextVisitDate, - info: DateFormat('EE dd/MM/yyyy').format(serviceRequest.nextVisitDate), - ), + serviceRequest.nextVisitDate == null + ? SizedBox.shrink() + : RequestInfoRow( + title: _subtitle.nextVisitDate, + info: DateFormat('EE dd/MM/yyyy').format(serviceRequest.nextVisitDate), + ), Row( children: [ Expanded( @@ -215,12 +225,12 @@ class RequestDetailsPage extends StatelessWidget { textScaleFactor: AppStyle.getScaleFactor(context), ), ), - StatusLabel(label: serviceRequest.statusLabel, - color: AColors.getRequestStatusColor(serviceRequest.statusValue) - ), + StatusLabel(label: serviceRequest.statusLabel, color: AColors.getRequestStatusColor(serviceRequest.statusValue)), ], ), - Divider(color: Theme.of(context).primaryColor,), + Divider( + color: Theme.of(context).primaryColor, + ), RequestInfoRow( title: _subtitle.hospital, info: serviceRequest.hospitalName, @@ -241,10 +251,10 @@ class RequestDetailsPage extends StatelessWidget { title: _subtitle.maintenanceIssue, content: serviceRequest.maintenanceIssue, ), - if(serviceRequest.audio?.isNotEmpty == true) - ASoundPlayer( - audio: serviceRequest.audio, - ), + if (serviceRequest.audio?.isNotEmpty == true) + ASoundPlayer( + audio: serviceRequest.audio, + ), // // Center( // child: Padding( @@ -286,65 +296,64 @@ class RequestDetailsPage extends StatelessWidget { // ) ], ), - serviceRequest.viewReport ? - ListView( - padding: EdgeInsets.symmetric(horizontal: 16), - children: [ - RequestInfoRow( - title: _subtitle.faultDescription, - content: serviceRequest.faultDescription, - ), - RequestInfoRow( - title: _subtitle.workPerformed, - content: serviceRequest.workPerformed, - ), - RequestInfoRow( - title: _subtitle.visitDate, - info: serviceRequest.visitDate, - ), - RequestInfoRow( - title: _subtitle.jobSheetNumber, - info: serviceRequest.jobSheetNumber, - ), - _userProvider.user.type == UsersTypes.engineer - && serviceRequest.reportID != null? - Padding( - padding: EdgeInsets.all(32), - child: AButton( - text: _subtitle.editServiceReport, - onPressed: (){ - Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => FutureServiceReport( - request: serviceRequest, + serviceRequest.viewReport + ? ListView( + padding: EdgeInsets.symmetric(horizontal: 16), + children: [ + RequestInfoRow( + title: _subtitle.faultDescription, + content: serviceRequest.faultDescription, + ), + RequestInfoRow( + title: _subtitle.workPerformed, + content: serviceRequest.workPerformed, + ), + RequestInfoRow( + title: _subtitle.visitDate, + info: serviceRequest.visitDate, + ), + RequestInfoRow( + title: _subtitle.jobSheetNumber, + info: serviceRequest.jobSheetNumber, + ), + _userProvider.user.type == UsersTypes.engineer && serviceRequest.reportID != null + ? Padding( + padding: EdgeInsets.all(32), + child: AButton( + text: _subtitle.editServiceReport, + onPressed: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => FutureServiceReport( + request: serviceRequest, + )), + ); + }, + ), ) + : SizedBox.shrink(), + ], + ) + : _userProvider.user.type == UsersTypes.engineer + ? Center( + child: Padding( + padding: EdgeInsets.all(32), + child: AButton( + text: "Create Report", + onPressed: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => CreateServiceReport( + request: serviceRequest, + )), + ); + }, + ), ), - ); - }, - ), - ): SizedBox.shrink(), - ], - ): - _userProvider.user.type == UsersTypes.engineer ? - Center( - child: Padding( - padding: EdgeInsets.all(32), - child: AButton( - text: "Create Report", - onPressed: (){ - Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => CreateServiceReport( - request: serviceRequest, - ) + ) + : Center( + child: ASubTitle(_subtitle.noDateFound), ), - ); - }, - ), - ), - ): Center(child: ASubTitle(_subtitle.noDateFound),), - - ], ), ), diff --git a/lib/views/pages/user/requests/requests_page.dart b/lib/views/pages/user/requests/requests_page.dart index 6c04d822..06160333 100644 --- a/lib/views/pages/user/requests/requests_page.dart +++ b/lib/views/pages/user/requests/requests_page.dart @@ -12,14 +12,14 @@ import 'package:test_sa/views/widgets/buttons/app_icon_button.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/requests/service_request_list.dart'; import 'package:test_sa/views/widgets/search/service_request_search_bar.dart'; + class ServiceRequestsPage extends StatefulWidget { static final String id = "/service-requests"; @override _ServiceRequestsPageState createState() => _ServiceRequestsPageState(); } -class _ServiceRequestsPageState extends State - with TickerProviderStateMixin{ +class _ServiceRequestsPageState extends State with TickerProviderStateMixin { ServiceRequestsProvider _serviceRequestsProvider; UserProvider _userProvider; SettingProvider _settingProvider; @@ -31,7 +31,7 @@ class _ServiceRequestsPageState extends State _userProvider = Provider.of(context); _settingProvider = Provider.of(context); Subtitle _subtitle = AppLocalization.of(context).subtitle; - if(_firstTime){ + if (_firstTime) { _serviceRequestsProvider.reset(); _firstTime = false; } @@ -45,9 +45,9 @@ class _ServiceRequestsPageState extends State onRefresh: () async { _serviceRequestsProvider.reset(); await _serviceRequestsProvider.getRequests( - user: _userProvider.user, - host: _settingProvider.host, - hospitalId: _userProvider.user.hospital?.id, + user: _userProvider.user, + host: _settingProvider.host, + hospitalId: _userProvider.user.clientId, ); }, child: Stack( @@ -55,8 +55,8 @@ class _ServiceRequestsPageState extends State Column( children: [ Container( - color:AColors.primaryColor, - padding: const EdgeInsets.symmetric(horizontal: 0,vertical: 4), + color: AColors.primaryColor, + padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4), child: Column( children: [ Row( @@ -66,10 +66,7 @@ class _ServiceRequestsPageState extends State child: Center( child: Text( _subtitle.serviceRequests, - style: Theme.of(context).textTheme.headline6.copyWith( - color: AColors.white, - fontStyle: FontStyle.italic - ), + style: Theme.of(context).textTheme.headline6.copyWith(color: AColors.white, fontStyle: FontStyle.italic), ), ), ), @@ -83,22 +80,23 @@ class _ServiceRequestsPageState extends State ServiceRequestSearch _temp = await showModalBottomSheet( context: context, isScrollControlled: true, - builder: (context){ + builder: (context) { return ServiceRequestsSearchDialog( initialSearchValue: _serviceRequestsProvider.search, ); }); - if(_temp != null){ + if (_temp != null) { _serviceRequestsProvider.search = _temp; _serviceRequestsProvider.reset(); setState(() {}); } }, ), - SizedBox(width: 16,) + SizedBox( + width: 16, + ) ], ), - ], ), ), @@ -107,9 +105,9 @@ class _ServiceRequestsPageState extends State nextPage: _serviceRequestsProvider.nextPage, onLazyLoad: () async { await _serviceRequestsProvider.getRequests( - user: _userProvider.user, - host: _settingProvider.host, - hospitalId: _userProvider.user.hospital.id, + user: _userProvider.user, + host: _settingProvider.host, + hospitalId: _userProvider.user.clientId, ); }, requests: _serviceRequestsProvider.serviceRequests, @@ -117,7 +115,6 @@ class _ServiceRequestsPageState extends State ), ], ), - ], ), ), diff --git a/lib/views/widgets/equipment/auto_complete_devices_field.dart b/lib/views/widgets/equipment/auto_complete_devices_field.dart index 3c6fbc99..0d45aa6e 100644 --- a/lib/views/widgets/equipment/auto_complete_devices_field.dart +++ b/lib/views/widgets/equipment/auto_complete_devices_field.dart @@ -8,6 +8,7 @@ import 'package:test_sa/models/device/device.dart'; import 'package:test_sa/views/app_style/colors.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; + class AutoCompleteDeviceField extends StatefulWidget { final Device initialValue; final int hospitalId; @@ -20,7 +21,6 @@ class AutoCompleteDeviceField extends StatefulWidget { } class _AutoCompleteDeviceFieldState extends State { - SettingProvider _settingProvider; DevicesProvider _devicesProvider; UserProvider _userProvider; @@ -37,6 +37,7 @@ class _AutoCompleteDeviceFieldState extends State { _controller.dispose(); super.dispose(); } + @override Widget build(BuildContext context) { _settingProvider = Provider.of(context); @@ -44,64 +45,53 @@ class _AutoCompleteDeviceFieldState extends State { _devicesProvider = Provider.of(context); //Subtitle _subtitle = AppLocalization.of(context).subtitle; return LoadingManager( - isLoading: _devicesProvider.isLoading, - isFailedLoading: _devicesProvider.devices == null, - stateCode: _devicesProvider.stateCode, - onRefresh: () async { - _devicesProvider.reset(); - await _devicesProvider.getEquipment( - host: _settingProvider.host, - user: _userProvider.user, - hospitalId: widget.hospitalId - ); - }, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 16 - ), - decoration: BoxDecoration( - color: Colors.white, - border: Border.all(color:AColors.black), - borderRadius: BorderRadius.circular( - AppStyle.borderRadius * AppStyle.getScaleFactor(context) - ), - boxShadow: [ - AppStyle.boxShadow - ] - ), - child: TypeAheadField( - textFieldConfiguration: TextFieldConfiguration( - style: Theme.of(context).textTheme.headline6, - controller: _controller, - textAlign: TextAlign.center, - decoration: const InputDecoration( - border: InputBorder.none, - disabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - enabledBorder: InputBorder.none, - ), - textInputAction: TextInputAction.search, + isLoading: _devicesProvider.isLoading, + isFailedLoading: _devicesProvider.devices == null, + stateCode: _devicesProvider.stateCode, + onRefresh: () async { + _devicesProvider.reset(); + await _devicesProvider.getEquipment(host: _settingProvider.host, user: _userProvider.user, hospitalId: widget.hospitalId); + }, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: AColors.black), + borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)), + boxShadow: [AppStyle.boxShadow]), + child: TypeAheadField( + textFieldConfiguration: TextFieldConfiguration( + style: Theme.of(context).textTheme.headline6, + controller: _controller, + textAlign: TextAlign.center, + decoration: const InputDecoration( + border: InputBorder.none, + disabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, ), - suggestionsCallback: (value) async { - return await _devicesProvider.getDevicesList( - host: _settingProvider.host, - user: _userProvider.user, - hospitalId: widget.hospitalId ?? _userProvider.user.hospital.id, - serialNumber: value, - ); - }, - itemBuilder: (context, device) { - return ListTile( - title: Text(device.serialNumber), - subtitle: Text("${device.modelDefinition.modelName}/${device.modelDefinition.manufacturerName}"), - ); - }, - onSuggestionSelected: (device) { - _controller.text = device.serialNumber; - widget.onPick(device.id); - }, + textInputAction: TextInputAction.search, ), + suggestionsCallback: (value) async { + return await _devicesProvider.getDevicesList( + host: _settingProvider.host, + user: _userProvider.user, + hospitalId: widget.hospitalId ?? _userProvider.user.clientId, + serialNumber: value, + ); + }, + itemBuilder: (context, device) { + return ListTile( + title: Text(device.serialNumber), + subtitle: Text("${device.modelDefinition.modelName}/${device.modelDefinition.manufacturerName}"), + ); + }, + onSuggestionSelected: (device) { + _controller.text = device.serialNumber; + widget.onPick(device.id); + }, ), + ), ); } } diff --git a/lib/views/widgets/equipment/single_device_picker.dart b/lib/views/widgets/equipment/single_device_picker.dart index 03b0d66f..ab36d5f4 100644 --- a/lib/views/widgets/equipment/single_device_picker.dart +++ b/lib/views/widgets/equipment/single_device_picker.dart @@ -11,9 +11,9 @@ import 'package:test_sa/views/widgets/equipment/device_item.dart'; import 'package:test_sa/views/widgets/loaders/lazy_loading.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/loaders/no_item_found.dart'; -import 'package:test_sa/views/widgets/qr/scan_qr.dart'; import '../app_text_form_field.dart'; + class SingleDevicePicker extends StatefulWidget { static final String id = "/single-device-Picker"; final bool sandraChoice = true; @@ -32,22 +32,16 @@ class _SingleDevicePickerState extends State { TextEditingController numberController = TextEditingController(); TextEditingController snController = TextEditingController(); _getDevice(String result) async { - if(result == null) return; + if (result == null) return; showDialog( barrierDismissible: false, context: context, - builder: (dialogContext){ + builder: (dialogContext) { return const Center(child: CircularProgressIndicator()); - } - ); - List devices = await _devicesProvider.getDevicesListBySN( - host: _settingProvider.host, - user: _userProvider.user, - hospitalId: _userProvider.user.hospital.id, - sn: result - ); + }); + List devices = await _devicesProvider.getDevicesListBySN(host: _settingProvider.host, user: _userProvider.user, hospitalId: _userProvider.user.clientId, sn: result); Navigator.of(context).pop(); - if(devices.isEmpty){ + if (devices.isEmpty) { Fluttertoast.showToast(msg: _subtitle.noDeviceFound); return; } @@ -72,7 +66,7 @@ class _SingleDevicePickerState extends State { _userProvider = Provider.of(context); _settingProvider = Provider.of(context); - if(_firstTime && _devicesProvider.devices != null){ + if (_firstTime && _devicesProvider.devices != null) { _searchableList.clear(); _searchableList.addAll(_devicesProvider.devices); } @@ -85,54 +79,42 @@ class _SingleDevicePickerState extends State { isFailedLoading: _devicesProvider.devices == null, onRefresh: () async { _devicesProvider.reset(); - await _devicesProvider.getEquipment( - user: _userProvider.user, - host: _settingProvider.host, - hospitalId: _userProvider.user.hospital?.id - ); + await _devicesProvider.getEquipment(user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId); }, child: Column( children: [ const SizedBox(height: 48), Padding( - padding: const EdgeInsets.symmetric(vertical: 8,horizontal: 16), + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), child: Column( children: [ ATextFormField( hintText: _subtitle.searchBySn, controller: snController, - style: Theme.of(context).textTheme.subtitle1, + style: Theme.of(context).textTheme.subtitle1, suffixIcon: const Icon(Icons.search_rounded), textInputAction: TextInputAction.search, onAction: () async { _devicesProvider.reset(); await _devicesProvider.getEquipment( - user: _userProvider.user, - host: _settingProvider.host, - hospitalId: _userProvider.user.hospital?.id, - serialNumber: snController.text, - number: numberController.text - ); + user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId, serialNumber: snController.text, number: numberController.text); _searchableList.clear(); _searchableList.addAll(_devicesProvider.devices); }, ), - const SizedBox(height: 8,), + const SizedBox( + height: 8, + ), ATextFormField( hintText: "Search by Number", controller: numberController, - style: Theme.of(context).textTheme.subtitle1, + style: Theme.of(context).textTheme.subtitle1, suffixIcon: const Icon(Icons.search_rounded), textInputAction: TextInputAction.search, onAction: () async { _devicesProvider.reset(); await _devicesProvider.getEquipment( - user: _userProvider.user, - host: _settingProvider.host, - hospitalId: _userProvider.user.hospital?.id, - serialNumber: snController.text, - number: numberController.text - ); + user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId, serialNumber: snController.text, number: numberController.text); _searchableList.clear(); _searchableList.addAll(_devicesProvider.devices); }, @@ -141,34 +123,30 @@ class _SingleDevicePickerState extends State { ), ), Expanded( - child: _searchableList.isEmpty ? - NoItemFound(message: _subtitle.noDeviceFound,): - LazyLoading( - nextPage: _devicesProvider.nextPage, - onLazyLoad: () async { - await _devicesProvider.getDevicesList( - user: _userProvider.user, - host: _settingProvider.host, - hospitalId: _userProvider.user.hospital?.id, - serialNumber: snController.text, - number: numberController.text - ); - }, - child:ListView.builder( - padding: EdgeInsets.zero, - shrinkWrap: true, - itemCount: _searchableList.length, - itemBuilder: (listContext,itemIndex){ - return DeviceItem( - device: _searchableList[itemIndex], - onPressed: (device){ - Navigator.of(context).pop(device); - }, - ); - }, - ), - ) - ), + child: _searchableList.isEmpty + ? NoItemFound( + message: _subtitle.noDeviceFound, + ) + : LazyLoading( + nextPage: _devicesProvider.nextPage, + onLazyLoad: () async { + await _devicesProvider.getDevicesList( + user: _userProvider.user, host: _settingProvider.host, hospitalId: _userProvider.user.clientId, serialNumber: snController.text, number: numberController.text); + }, + child: ListView.builder( + padding: EdgeInsets.zero, + shrinkWrap: true, + itemCount: _searchableList.length, + itemBuilder: (listContext, itemIndex) { + return DeviceItem( + device: _searchableList[itemIndex], + onPressed: (device) { + Navigator.of(context).pop(device); + }, + ); + }, + ), + )), ], ), ), diff --git a/lib/views/widgets/pentry/pentry_calibration_tool_form.dart b/lib/views/widgets/pentry/pentry_calibration_tool_form.dart index 7ecdaed6..048e113c 100644 --- a/lib/views/widgets/pentry/pentry_calibration_tool_form.dart +++ b/lib/views/widgets/pentry/pentry_calibration_tool_form.dart @@ -71,7 +71,7 @@ class _PentryCalibrationToolFormState extends State { ), AutoCompleteDeviceNumberField( initialValue: model.assetsNumber, - hospitalId: userProvider.user.hospital?.id, + hospitalId: userProvider.user.clientId, onPick: (number) { model.assetsNumber = number; }, diff --git a/lib/views/widgets/requests/service_request_update_dialog.dart b/lib/views/widgets/requests/service_request_update_dialog.dart index e2680384..ce8cae93 100644 --- a/lib/views/widgets/requests/service_request_update_dialog.dart +++ b/lib/views/widgets/requests/service_request_update_dialog.dart @@ -54,8 +54,7 @@ class _ServiceRequestsUpdateDialogState extends State(context); + final userProvider = Provider.of(context); + final menuProvider = Provider.of(context); + return LoadingManager( + isLoading: menuProvider.isLoading, + isFailedLoading: menuProvider.items == null, + stateCode: menuProvider.stateCode, + onRefresh: () async { + menuProvider.reset(); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); + }, + child: SingleStatusMenu( + initialStatus: initialValue, + statuses: menuProvider.items, + onSelect: onSelect, + ), + ); + } +} diff --git a/lib/views/widgets/status/service_request/service_request_loan_availability.dart b/lib/views/widgets/status/service_request/service_request_loan_availability.dart new file mode 100644 index 00000000..31cb3f33 --- /dev/null +++ b/lib/views/widgets/status/service_request/service_request_loan_availability.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/controllers/providers/api/user_provider.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; +import 'package:test_sa/models/lookup.dart'; +import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; +import 'package:test_sa/views/widgets/status/single_status_menu.dart'; + +import '../../../../controllers/providers/api/status_drop_down/service_reqest/service_request_loan_availability_provider.dart'; + +class ServiceRequestedLoanAvailability extends StatelessWidget { + final Function(Lookup) onSelect; + final Lookup initialValue; + + const ServiceRequestedLoanAvailability({Key key, this.onSelect, this.initialValue}) : super(key: key); + @override + Widget build(BuildContext context) { + final settingProvider = Provider.of(context); + final userProvider = Provider.of(context); + final menuProvider = Provider.of(context); + return LoadingManager( + isLoading: menuProvider.isLoading, + isFailedLoading: menuProvider.items == null, + stateCode: menuProvider.stateCode, + onRefresh: () async { + menuProvider.reset(); + await menuProvider.getData(user: userProvider.user, host: settingProvider.host); + }, + child: SingleStatusMenu( + initialStatus: initialValue, + statuses: menuProvider.items, + onSelect: onSelect, + )); + } +}