From 3a20bf00172141b1a6908e257882de9bd41852b4 Mon Sep 17 00:00:00 2001 From: zaid_daoud Date: Sun, 12 Mar 2023 09:20:33 +0300 Subject: [PATCH] Track Service Filter DONE && Preventive Maintenance DONE --- lib/api/api_client.dart | 4 +- .../preventive_maintenance_api_client.dart | 54 +++++ lib/api/service_request_api_client.dart | 14 +- lib/api/user_api_client.dart | 3 - lib/api/visits_api_client.dart | 64 +++++ .../providers/api/devices_provider.dart | 2 +- ...reventive_maintenance_visits_provider.dart | 169 ++++++------- .../api/regular_visits_provider.dart | 225 +++++++----------- .../api/service_requests_provider.dart | 24 +- .../providers/loading_notifier.dart | 2 +- .../service_request_search.dart | 29 +-- lib/models/visits/visits_search.dart | 55 +---- lib/views/pages/user/report_issues_page.dart | 2 +- .../report/create_service_report.dart | 2 +- .../requests/report/edit_service_report.dart | 2 +- .../pages/user/requests/request_details.dart | 2 +- .../pages/user/requests/requests_page.dart | 6 +- .../pages/user/visits/pantry/edit_pentry.dart | 45 +--- .../visits/pantry/future_edit_pently.dart | 4 +- .../preventive_maintenance_visits_page.dart | 125 +++------- .../user/visits/regular_visits_page.dart | 99 ++------ .../pages/user/visits/visit_details.dart | 26 +- lib/views/widgets/loaders/lazy_loading.dart | 20 +- .../widgets/loaders/loading_manager.dart | 4 +- .../service_request_update_dialog.dart | 4 +- .../search/service_request_search_bar.dart | 2 +- .../widgets/search/visits_search_bar.dart | 2 +- 27 files changed, 428 insertions(+), 562 deletions(-) create mode 100644 lib/api/preventive_maintenance_api_client.dart create mode 100644 lib/api/visits_api_client.dart diff --git a/lib/api/api_client.dart b/lib/api/api_client.dart index 49c3e2d4..d9ffd0ce 100644 --- a/lib/api/api_client.dart +++ b/lib/api/api_client.dart @@ -66,7 +66,7 @@ class ApiClient { factory ApiClient() => _instance; Future postJsonForObject(FactoryConstructor factoryConstructor, String url, T jsonObject, - {String? token, Map? queryParameters, Map? headers, int retryTimes = 0, bool isFormData = false}) async { + {String? token, Map? queryParameters, Map? headers, int retryTimes = 0, bool isFormData = true}) async { var defaultHeaders = {'Accept': 'application/json'}; if (headers != null && headers.isNotEmpty) { defaultHeaders.addAll(headers); @@ -97,7 +97,7 @@ class ApiClient { } Future postJsonForResponse(String url, T jsonObject, - {String? token, Map? queryParameters, Map? headers, int retryTimes = 0, bool isFormData = false}) async { + {String? token, Map? queryParameters, Map? headers, int retryTimes = 0, bool isFormData = true}) async { int currentRetryTime = retryTimes; String? requestBody; late Map stringObj; diff --git a/lib/api/preventive_maintenance_api_client.dart b/lib/api/preventive_maintenance_api_client.dart new file mode 100644 index 00000000..00814d77 --- /dev/null +++ b/lib/api/preventive_maintenance_api_client.dart @@ -0,0 +1,54 @@ +import 'dart:convert'; + +import 'package:test_sa/api/api_client.dart'; +import 'package:test_sa/api/user_api_client.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/visits/visits_group.dart'; +import 'package:test_sa/models/visits/visits_search.dart'; + +import '../models/visits/visit.dart'; + +class PreventiveMaintenanceApiClient { + static final PreventiveMaintenanceApiClient _instance = PreventiveMaintenanceApiClient._internal(); + + /// ## list of user requests + final List visits = []; + + PreventiveMaintenanceApiClient._internal(); + + factory PreventiveMaintenanceApiClient() => _instance; + + Future getVisits({required int pageItemNumber, VisitsSearch? visitsSearch}) async { + final response = await ApiClient().getJsonForResponse( + '${URLs.host1}${URLs.getPreventiveMaintenanceVisits}', + headers: {"Content-Type": "application/json; charset=utf-8"}, + queryParameters: { + 'uid': UserApiClient().user?.id, + 'token': UserApiClient().user?.token, + 'page': '${(visits.length) ~/ pageItemNumber}', + if (visitsSearch != null) ...visitsSearch.queryParameters(), + }, + ); + List requestsListJson = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", "")); + List visitsList = requestsListJson.map((request) => Visit.fromJson(request)).toList(); + visits.addAll(visitsList); + } + + Future updateGroupOfVisits({required VisitsGroup group}) async { + final user = UserApiClient().user; + Map body = group.toJson(); + body["token"] = user?.token ?? ""; + body["uid"] = user?.id ?? ""; + //userId = 397.toString(); // testing id to view data + await ApiClient().postJsonForResponse( + '${URLs.host1}${URLs.updatePreventiveMaintenanceVisits}', + body, + ); + // client's request was successfully received + for (var visit in (group.visits ?? [])) { + visit.status = group.status; + visit.actualDate = group.date.toString().split(" ").first; + } + group.visits?.clear(); + } +} diff --git a/lib/api/service_request_api_client.dart b/lib/api/service_request_api_client.dart index 03a9e5c5..2e35eef9 100644 --- a/lib/api/service_request_api_client.dart +++ b/lib/api/service_request_api_client.dart @@ -40,7 +40,6 @@ class ServiceRequestApiClient { "defect_types": (serviceRequest.defectType?.id).toString(), "audio": serviceRequest.audio, }, - isFormData: true, ); } @@ -54,7 +53,8 @@ class ServiceRequestApiClient { 'uid': user?.id, if (user?.hospital?.id != null) 'client_nid': user?.hospital?.id, 'token': user?.token, - 'page': '${(serviceRequests.length) ~/ pageItemNumber}${search?.toSearchString()}', + 'page': '${(serviceRequests.length) ~/ pageItemNumber}', + if (search != null) ...search.queryParameters(), }, ); List requestsListJson = json.decode(utf8.decode(response.bodyBytes)); @@ -80,7 +80,7 @@ class ServiceRequestApiClient { Map body = issue.toMap(); body["uid"] = user?.id ?? ""; body["token"] = user?.token ?? ""; - await ApiClient().postJsonForResponse('${URLs.host1}${URLs.createReport}', body, isFormData: true); + await ApiClient().postJsonForResponse('${URLs.host1}${URLs.createReport}', body); } Future updateDate({String? newDate, Lookup? employee, ServiceRequest? request}) async { @@ -91,7 +91,7 @@ class ServiceRequestApiClient { body["nid"] = request?.id ?? ''; body["date"] = newDate ?? ''; body["ass_emp"] = employee?.id?.toString() ?? ''; - await ApiClient().postJsonForResponse('${URLs.host1}${URLs.updateRequestDate}', body, isFormData: true); + await ApiClient().postJsonForResponse('${URLs.host1}${URLs.updateRequestDate}', body); request?.engineerName = employee?.label; } @@ -101,7 +101,7 @@ class ServiceRequestApiClient { body?["uid"] = user?.id ?? ""; body?["token"] = user?.token ?? ""; body?["job_id"] = request?.id ?? ''; - await ApiClient().postJsonForResponse('${URLs.host1}${URLs.createServiceReport}', body, isFormData: true); + await ApiClient().postJsonForResponse('${URLs.host1}${URLs.createServiceReport}', body); } Future createDuplicatedReport({required ServiceRequest request}) async { @@ -119,7 +119,7 @@ class ServiceRequestApiClient { body["token"] = user?.token ?? ""; body["job_id"] = request.id ?? ''; body["report_id"] = request.reportID ?? ''; - await ApiClient().postJsonForResponse('${URLs.host1}${URLs.updateServiceReport}', body, isFormData: true); + await ApiClient().postJsonForResponse('${URLs.host1}${URLs.updateServiceReport}', body); } Future updateServiceReportTimer({required TimerModel timer, required ServiceRequest request}) async { @@ -132,7 +132,7 @@ class ServiceRequestApiClient { body["end_time"] = ((timer.endAt?.millisecondsSinceEpoch ?? 0) / 1000).toStringAsFixed(0); body["working_hours"] = ((timer.durationInSecond ?? 0) / 60 / 60).toStringAsFixed(5); body["report_id"] = request.reportID ?? ''; - await ApiClient().postJsonForResponse('${URLs.host1}${URLs.updateServiceReport}', body, isFormData: true); + await ApiClient().postJsonForResponse('${URLs.host1}${URLs.updateServiceReport}', body); } Future getSingleServiceReport({required String reportId}) async { diff --git a/lib/api/user_api_client.dart b/lib/api/user_api_client.dart index 370d7052..b11b8887 100644 --- a/lib/api/user_api_client.dart +++ b/lib/api/user_api_client.dart @@ -25,7 +25,6 @@ class UserApiClient { }, "${URLs.host1}${URLs.login}", await user.toLoginJson(), //body - isFormData: true, ); } @@ -41,7 +40,6 @@ class UserApiClient { }, "${URLs.host1}${URLs.register}", await newUser.toRegisterJson(), //body - isFormData: true, ); } @@ -57,7 +55,6 @@ class UserApiClient { }, "${URLs.host1}${URLs.updateProfile}", updatedUser.toUpdateProfileJson(), //body - isFormData: true, ); // Map jsonObject = {}; // jsonObject["uid"] = user.id; diff --git a/lib/api/visits_api_client.dart b/lib/api/visits_api_client.dart new file mode 100644 index 00000000..8bbfa309 --- /dev/null +++ b/lib/api/visits_api_client.dart @@ -0,0 +1,64 @@ +import 'dart:convert'; + +import 'package:test_sa/api/api_client.dart'; +import 'package:test_sa/api/user_api_client.dart'; +import 'package:test_sa/controllers/api_routes/urls.dart'; +import 'package:test_sa/models/pantry/pentry.dart'; +import 'package:test_sa/models/visits/visits_group.dart'; +import 'package:test_sa/models/visits/visits_search.dart'; + +import '../models/visits/visit.dart'; + +class VisitsApiClient { + static final VisitsApiClient _instance = VisitsApiClient._internal(); + + /// ## list of user requests + final List visits = []; + + VisitsApiClient._internal(); + + factory VisitsApiClient() => _instance; + + Future getVisits({required int pageItemNumber, VisitsSearch? visitsSearch}) async { + final response = await ApiClient().getJsonForResponse( + '${URLs.host1}${URLs.getRegularVisits}', + headers: {"Content-Type": "application/json; charset=utf-8"}, + queryParameters: { + 'uid': UserApiClient().user?.id, + 'token': UserApiClient().user?.token, + 'page': '${(visits.length) ~/ pageItemNumber}', + if (visitsSearch != null) ...visitsSearch.queryParameters(), + }, + ); + List requestsListJson = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", "")); + List visitsList = requestsListJson.map((request) => Visit.fromJson(request)).toList(); + visits.addAll(visitsList); + } + + Future updateGroupOfVisits({required VisitsGroup group}) async { + final user = UserApiClient().user; + Map body = group.toJson(); + body["token"] = user?.token ?? ""; + body["uid"] = user?.id ?? ""; + //userId = 397.toString(); // testing id to view data + await ApiClient().postJsonForResponse('${URLs.host1}${URLs.updateRegularVisits}', body); + } + + Future getPentry(String id) async { + final response = await ApiClient().getJsonForResponse( + '${URLs.host1}${URLs.getPentry}/$id', + headers: {"Content-Type": "application/json; charset=utf-8"}, + ); + + return Pentry.fromMap(json.decode(utf8.decode(response.bodyBytes))); + } + + Future updatePentry({Pentry? pentry, Visit? visit}) async { + final user = UserApiClient().user; + Map? body = pentry?.toMap(); + body?["uid"] = user?.id ?? ""; + body?["token"] = user?.token ?? ""; + await ApiClient().postJsonForResponse('${URLs.host1}${URLs.updatePentry}/${visit?.id}', body); + visit?.status = pentry?.ppmVisitStatus; + } +} diff --git a/lib/controllers/providers/api/devices_provider.dart b/lib/controllers/providers/api/devices_provider.dart index 14f88cae..ed1f7c4b 100644 --- a/lib/controllers/providers/api/devices_provider.dart +++ b/lib/controllers/providers/api/devices_provider.dart @@ -28,7 +28,7 @@ class DevicesProvider extends LoadingNotifier { Future getEquipment({required String? hospitalId}) async { if (hospitalId != null) { _searchableList.clear(); - waitApiRequest( + await waitApiRequest( () async { await DevicesApiClient().getEquipment(hospitalId); _searchableList.addAll(DevicesApiClient().devices); diff --git a/lib/controllers/providers/api/preventive_maintenance_visits_provider.dart b/lib/controllers/providers/api/preventive_maintenance_visits_provider.dart index b943f3f3..6cfe2171 100644 --- a/lib/controllers/providers/api/preventive_maintenance_visits_provider.dart +++ b/lib/controllers/providers/api/preventive_maintenance_visits_provider.dart @@ -1,21 +1,22 @@ -import 'dart:convert'; - import 'package:flutter/cupertino.dart'; -import 'package:http/http.dart'; +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:test_sa/api/preventive_maintenance_api_client.dart'; +import 'package:test_sa/controllers/providers/loading_notifier.dart'; -import '../../../models/user.dart'; -import '../../../models/visits/visit.dart'; import '../../../models/visits/visits_group.dart'; import '../../../models/visits/visits_search.dart'; -import '../../api_routes/urls.dart'; +import '../../../views/pages/user/visits/update_visits_group_sheet.dart'; +import '../../http_status_manger/http_status_manger.dart'; +import '../../localization/localization.dart'; -class PreventiveMaintenanceVisitsProvider extends ChangeNotifier { +class PreventiveMaintenanceVisitsProvider extends LoadingNotifier { // number of items call in each request final pageItemNumber = 50; //reset provider data void reset() { - visits = null; + PreventiveMaintenanceApiClient().visits.clear(); nextPage = true; stateCode = null; } @@ -28,98 +29,76 @@ class PreventiveMaintenanceVisitsProvider extends ChangeNotifier { // true if there is next page in product list and false if not bool? nextPage = true; - // list of user requests - List? visits; - - // when requests in-process _loading = true - // done _loading = true - // failed _loading = false - bool? isLoading; - VisitsSearch? visitsSearch = VisitsSearch(); - /// 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 getVisits({ - required String host, - required User user, - // VisitsSearch visitsSearch, - }) async { - if (isLoading == true) return -2; - isLoading = true; - Response response; - //userId = 397.toString(); // testing id to view data - try { - response = await get( - Uri.parse( - "${host + URLs.getPreventiveMaintenanceVisits}?uid=${user.id}&token=${user.token}&page=${(visits?.length ?? 0) ~/ pageItemNumber}${visitsSearch?.toSearchString()}", - ), - headers: {"Content-Type": "application/json; charset=utf-8"}, - ); - } catch (error) { - isLoading = false; - stateCode = -1; - notifyListeners(); - return -1; - } - stateCode = response.statusCode; - if (response.statusCode >= 200 && response.statusCode < 300) { - // client's request was successfully received - List requestsListJson = json.decode(utf8.decode(response.bodyBytes)); - List visits = requestsListJson.map((request) => Visit.fromJson(request)).toList(); - visits.addAll(visits); - if (visits.length == pageItemNumber) { - nextPage = true; - } else { - nextPage = false; - } - } - isLoading = false; - notifyListeners(); - return response.statusCode; + Future getVisits() async { + await waitApiRequest( + () async { + await PreventiveMaintenanceApiClient().getVisits(pageItemNumber: pageItemNumber, visitsSearch: visitsSearch); + }, + onSuccess: () { + /// TODO : this is temporary + stateCode = 200; + if (PreventiveMaintenanceApiClient().visits.length == pageItemNumber) { + nextPage = true; + } else { + nextPage = false; + } + }, + onError: (error) { + /// TODO : this is temporary + stateCode = error.error?.errorCode; + }, + ); } - /// return -2 if request in progress - /// return -1 if error happen when sending request - /// return state code if request complete may be 200, 404 or 403 - /// for more details check http state manager - /// lib\controllers\http_status_manger\http_status_manger.dart - Future updateGroupOfVisits({ - required String host, - required User user, - required VisitsGroup group, - }) async { - Response response; - Map body = group.toJson(); - body["token"] = user.token ?? ""; - body["uid"] = user.id ?? ""; - //userId = 397.toString(); // testing id to view data - try { - response = await post( - Uri.parse(host + URLs.updatePreventiveMaintenanceVisits), - body: body, + Future updateGroupOfVisits(BuildContext context) async { + final subtitle = AppLocalization.of(context)?.subtitle; + VisitsGroup? group = await showModalBottomSheet( + isScrollControlled: true, + context: context, + builder: (context) { + return UpdateVisitsGroupSheet(visits: PreventiveMaintenanceApiClient().visits, title: subtitle?.updatePreventiveMaintenance); + }, + ) as VisitsGroup?; + if (context.mounted && group != null) { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return CupertinoAlertDialog( + title: Text(subtitle?.updatingDots ?? ''), + content: const Center(child: CircularProgressIndicator()), + ); + }, + ); + await waitApiRequest( + () async { + await PreventiveMaintenanceApiClient().updateGroupOfVisits(group: group); + if (context.mounted) { + Navigator.of(context).pop(); + } + }, + onSuccess: () { + /// TODO : this is temporary + stateCode = 200; + Navigator.of(context).pop(); + Fluttertoast.showToast( + msg: subtitle?.regularVisitsUpdatedSuccessfully ?? '', + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + ); + }, + onError: (error) { + /// TODO : this is temporary + stateCode = error.error?.errorCode; + Fluttertoast.showToast( + msg: HttpStatusManger.getStatusMessage(status: error.error?.errorCode, subtitle: subtitle), + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + ); + }, ); - - stateCode = response.statusCode; - if (response.statusCode >= 200 && response.statusCode < 300) { - // client's request was successfully received - for (var visit in (group.visits ?? [])) { - visit.status = group.status; - visit.actualDate = group.date.toString().split(" ").first; - } - group.visits?.clear(); - notifyListeners(); - } - - return response.statusCode; - } catch (error) { - isLoading = false; - stateCode = -1; - notifyListeners(); - return -1; } } } diff --git a/lib/controllers/providers/api/regular_visits_provider.dart b/lib/controllers/providers/api/regular_visits_provider.dart index 0d66fb34..447bcddd 100644 --- a/lib/controllers/providers/api/regular_visits_provider.dart +++ b/lib/controllers/providers/api/regular_visits_provider.dart @@ -1,22 +1,24 @@ -import 'dart:convert'; - import 'package:flutter/cupertino.dart'; -import 'package:http/http.dart'; +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:test_sa/api/visits_api_client.dart'; +import 'package:test_sa/controllers/providers/loading_notifier.dart'; import '../../../models/pantry/pentry.dart'; -import '../../../models/user.dart'; import '../../../models/visits/visit.dart'; import '../../../models/visits/visits_group.dart'; import '../../../models/visits/visits_search.dart'; -import '../../api_routes/urls.dart'; +import '../../../views/pages/user/visits/update_visits_group_sheet.dart'; +import '../../http_status_manger/http_status_manger.dart'; +import '../../localization/localization.dart'; -class RegularVisitsProvider extends ChangeNotifier { +class RegularVisitsProvider extends LoadingNotifier { // number of items call in each request final pageItemNumber = 50; - //reset provider data + // reset provider data void reset() { - visits.clear(); + VisitsApiClient().visits.clear(); nextPage = true; stateCode = null; } @@ -29,145 +31,100 @@ class RegularVisitsProvider extends ChangeNotifier { // true if there is next page in product list and false if not bool nextPage = true; - // list of user requests - List visits = []; - - // when requests in-process _loading = true - // done _loading = true - // failed _loading = false - bool? isLoading; - VisitsSearch? visitsSearch = VisitsSearch(); - /// 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 getVisits({ - required String? host, - required User? user, - // VisitsSearch visitsSearch, - }) async { - if (isLoading == true) { - return -2; - } - isLoading = true; - Response response; - //userId = 397.toString(); // testing id to view data - try { - response = await get( - Uri.parse( - "$host${URLs.getRegularVisits}?uid=${user?.id}&token=${user?.token}&page=${(visits.length) ~/ pageItemNumber}${visitsSearch?.toSearchString()}", - ), - headers: {"Content-Type": "application/json; charset=utf-8"}, - ); - } catch (error) { - isLoading = false; - stateCode = -1; - notifyListeners(); - return -1; - } - stateCode = response.statusCode; - if (response.statusCode >= 200 && response.statusCode < 300) { - // client's request was successfully received - try { - List requestsListJson = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", "")); - List visitsList = requestsListJson.map((request) => Visit.fromJson(request)).toList(); - visits.addAll(visitsList); - if (visits.length == pageItemNumber) { + Future getVisits() async { + await waitApiRequest( + () async { + await VisitsApiClient().getVisits(pageItemNumber: pageItemNumber, visitsSearch: visitsSearch); + }, + onSuccess: () { + /// TODO : this is temporary + stateCode = 200; + if (VisitsApiClient().visits.length == pageItemNumber) { nextPage = true; } else { nextPage = false; } - } catch (error) { - isLoading = false; - stateCode = -1; - notifyListeners(); - return -1; - } - } - isLoading = false; - notifyListeners(); - return response.statusCode; + }, + onError: (error) { + /// TODO : this is temporary + stateCode = error.error?.errorCode; + }, + ); } - /// return -2 if request in progress - /// return -1 if error happen when sending request - /// return state code if request complete may be 200, 404 or 403 - /// for more details check http state manager - /// lib\controllers\http_status_manger\http_status_manger.dart - Future updateGroupOfVisits({ - required String host, - required User user, - required VisitsGroup group, - }) async { - Response response; - Map body = group.toJson(); - body["token"] = user.token ?? ""; - body["uid"] = user.id ?? ""; - //userId = 397.toString(); // testing id to view data - try { - response = await post( - Uri.parse(host + URLs.updateRegularVisits), - body: body, + Future updateGroupOfVisits(BuildContext context) async { + final subtitle = AppLocalization.of(context)?.subtitle; + VisitsGroup? group = await showModalBottomSheet( + isScrollControlled: true, + context: context, + builder: (context) { + return UpdateVisitsGroupSheet(visits: VisitsApiClient().visits, title: subtitle?.updateRegularVisits); + }, + ) as VisitsGroup?; + if (context.mounted && group != null) { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return CupertinoAlertDialog( + title: Text(subtitle?.updatingDots ?? ''), + content: const Center(child: CircularProgressIndicator()), + ); + }, + ); + await waitApiRequest( + () async { + await VisitsApiClient().updateGroupOfVisits(group: group); + reset(); + }, + onSuccess: () { + /// TODO : this is temporary + stateCode = 200; + Navigator.of(context).pop(); + Fluttertoast.showToast( + msg: subtitle?.regularVisitsUpdatedSuccessfully ?? '', + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + ); + }, + onError: (error) { + /// TODO : this is temporary + stateCode = error.error?.errorCode; + Fluttertoast.showToast( + msg: HttpStatusManger.getStatusMessage(status: error.error?.errorCode, subtitle: subtitle), + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.BOTTOM, + ); + }, ); - stateCode = response.statusCode; - if (response.statusCode >= 200 && response.statusCode < 300) { - // client's request was successfully received - reset(); - notifyListeners(); - } - - return response.statusCode; - } catch (error) { - isLoading = false; - stateCode = -1; - notifyListeners(); - return -1; } } - Future getPently({ - required String host, - required User user, - required String id, - }) async { - Response response; - response = await get( - Uri.parse("$host${URLs.getPentry}/$id"), - headers: {"Content-Type": "application/json; charset=utf-8"}, - ); - - Pentry? pantry; - if (response.statusCode >= 200 && response.statusCode < 300) { - pantry = Pentry.fromMap(json.decode(utf8.decode(response.bodyBytes))); - } - return pantry; + Future getPently({required String? id}) async { + return id == null ? null : await VisitsApiClient().getPentry(id); } - Future updatePentry({ - required String? host, - required User? user, - required Pentry? pentry, - required Visit? visit, - }) async { - try { - Response response; - Map? body = pentry?.toMap(); - body?["uid"] = user?.id ?? ""; - body?["token"] = user?.token ?? ""; - response = await post( - Uri.parse("$host${URLs.updatePentry}/${visit?.id}"), - body: body, - ); - if (response.statusCode >= 200 && response.statusCode < 300) { - visit?.status = pentry?.ppmVisitStatus; - notifyListeners(); - } - return response.statusCode; - } catch (error) { - return -1; - } + void updatePentry(BuildContext context, {required Pentry? pentry, required Visit? visit}) async { + final subtitle = AppLocalization.of(context)?.subtitle; + await waitApiRequest( + () async { + await VisitsApiClient().updatePentry(pentry: pentry, visit: visit); + }, + onSuccess: () { + /// TODO : this is temporary + stateCode = 200; + if (subtitle != null) { + Fluttertoast.showToast(msg: subtitle.requestCompleteSuccessfully); + } + }, + onError: (error) { + /// TODO : this is temporary + stateCode = error.error?.errorCode; + String errorMessage = HttpStatusManger.getStatusMessage(status: error.error?.errorCode, subtitle: subtitle); + Fluttertoast.showToast(msg: errorMessage); + }, + ); } } diff --git a/lib/controllers/providers/api/service_requests_provider.dart b/lib/controllers/providers/api/service_requests_provider.dart index de6ba0d5..ddb7623d 100644 --- a/lib/controllers/providers/api/service_requests_provider.dart +++ b/lib/controllers/providers/api/service_requests_provider.dart @@ -40,8 +40,8 @@ class ServiceRequestsProvider extends LoadingNotifier { ServiceRequestSearch? search = ServiceRequestSearch(); /// Get Service Requests and Fill [ServiceRequestApiClient.serviceRequests] - void getRequests() async { - waitApiRequest(() async { + Future getRequests() async { + await waitApiRequest(() async { final serviceRequestsPage = await ServiceRequestApiClient().getRequests(pageItemNumber: pageItemNumber, search: search); if (serviceRequestsPage.length == pageItemNumber) { nextPage = true; @@ -86,8 +86,8 @@ class ServiceRequestsProvider extends LoadingNotifier { }); } - void createIssueReport(BuildContext context, {required Issue issue}) async { - waitApiRequest(() async { + Future createIssueReport(BuildContext context, {required Issue issue}) async { + await waitApiRequest(() async { await ServiceRequestApiClient().createIssueReport(issue); }, onSuccess: () { final subtitle = AppLocalization.of(context)?.subtitle; @@ -101,7 +101,7 @@ class ServiceRequestsProvider extends LoadingNotifier { }); } - void updateDate(BuildContext context, {required String? newDate, required Lookup? employee, required ServiceRequest? request}) { + Future updateDate(BuildContext context, {required String? newDate, required Lookup? employee, required ServiceRequest? request}) async { final subtitle = AppLocalization.of(context)?.subtitle; showDialog( context: context, @@ -110,7 +110,7 @@ class ServiceRequestsProvider extends LoadingNotifier { return CupertinoAlertDialog(title: Text(subtitle?.updatingDots ?? ''), content: const Center(child: CircularProgressIndicator())); }, ); - waitApiRequest( + await waitApiRequest( () async { await ServiceRequestApiClient().updateDate(newDate: newDate, employee: employee, request: request); }, @@ -128,9 +128,9 @@ class ServiceRequestsProvider extends LoadingNotifier { ); } - void createServiceReport(BuildContext context, {required ServiceReport? report, required ServiceRequest? request}) async { + Future createServiceReport(BuildContext context, {required ServiceReport? report, required ServiceRequest? request}) async { final subtitle = AppLocalization.of(context)?.subtitle; - waitApiRequest( + await waitApiRequest( () async { await ServiceRequestApiClient().createServiceReport(report: report, request: request); reset(); @@ -151,7 +151,7 @@ class ServiceRequestsProvider extends LoadingNotifier { ); } - void createDuplicatedReport(BuildContext context, {required ServiceRequest request}) async { + Future createDuplicatedReport(BuildContext context, {required ServiceRequest request}) async { final subtitle = AppLocalization.of(context)?.subtitle; bool result = await showDialog(context: context, builder: (_) => AAlertDialog(title: subtitle?.duplicateAlert, content: subtitle?.duplicateAlertMessage)); if (result == true && context.mounted) { @@ -161,7 +161,7 @@ class ServiceRequestsProvider extends LoadingNotifier { return const Center(child: CircularProgressIndicator()); }, ); - waitApiRequest( + await waitApiRequest( () async { await ServiceRequestApiClient().createDuplicatedReport(request: request); reset(); @@ -179,9 +179,9 @@ class ServiceRequestsProvider extends LoadingNotifier { } } - void updateServiceReport(BuildContext context, {required ServiceReport report, required ServiceRequest request}) { + Future updateServiceReport(BuildContext context, {required ServiceReport report, required ServiceRequest request}) async { final subtitle = AppLocalization.of(context)?.subtitle; - waitApiRequest( + await waitApiRequest( () async { await ServiceRequestApiClient().updateServiceReport(report: report, request: request); reset(); diff --git a/lib/controllers/providers/loading_notifier.dart b/lib/controllers/providers/loading_notifier.dart index 5d800b2d..b849956d 100644 --- a/lib/controllers/providers/loading_notifier.dart +++ b/lib/controllers/providers/loading_notifier.dart @@ -13,7 +13,7 @@ class LoadingNotifier with ChangeNotifier { /// - [fun] : Callback function that contains the API request. /// - [onError] : Optional callback function to handle the request on failure with [APIException] parameter. /// - [onSuccess] : Optional callback function to handle the request on succeed. - void waitApiRequest(Function fun, {Function(APIException)? onError, Function? onSuccess}) async { + Future waitApiRequest(Function fun, {Function(APIException)? onError, Function? onSuccess}) async { if (_loading == true) { debugPrint('loading_notifier.dart : another action already started'); return; diff --git a/lib/models/service_request/service_request_search.dart b/lib/models/service_request/service_request_search.dart index 5f381d20..bd617b58 100644 --- a/lib/models/service_request/service_request_search.dart +++ b/lib/models/service_request/service_request_search.dart @@ -20,26 +20,13 @@ class ServiceRequestSearch { model = newSearch.model; } - String toSearchString() { - String search = ""; - if (deviceSerialNumber != null && (deviceSerialNumber?.isNotEmpty ?? false)) { - search += "&sn_id=$deviceSerialNumber"; - } - - if (statusValue != null) { - search += "&status=$statusValue"; - } - - if (deviceName != null && (deviceName?.isNotEmpty ?? false)) { - search += "&equipment_en_name=$deviceName"; - } - - if (hospital != null && (hospital?.isNotEmpty ?? false)) { - search += "&client=$hospital"; - } - if (model != null && (model?.isNotEmpty ?? false)) { - search += "&model=$model"; - } - return search; + Map queryParameters() { + return { + if (deviceSerialNumber != null && (deviceSerialNumber?.isNotEmpty ?? false)) 'sn_id': deviceSerialNumber, + if (statusValue != null) 'status': statusValue?.toString(), + if (deviceName != null && (deviceName?.isNotEmpty ?? false)) 'equipment_en_name': deviceName, + if (hospital != null && (hospital?.isNotEmpty ?? false)) 'client': hospital, + if (model != null && (model?.isNotEmpty ?? false)) 'model': model, + }; } } diff --git a/lib/models/visits/visits_search.dart b/lib/models/visits/visits_search.dart index 9620c3e7..f4d2b9e2 100644 --- a/lib/models/visits/visits_search.dart +++ b/lib/models/visits/visits_search.dart @@ -36,47 +36,18 @@ class VisitsSearch { statusValue = newSearch.statusValue; } - String toSearchString() { - String _search = ""; - if (deviceSerialNumber != null && (deviceSerialNumber?.isNotEmpty ?? false)) { - _search += "&sn_id=$deviceSerialNumber"; - } - - if (hospitalName != null && (hospitalName?.isNotEmpty ?? false)) { - _search += "&client=$hospitalName"; - } - - if (brand != null && (brand?.isNotEmpty ?? false)) { - _search += "&brand=$brand"; - } - - if (model != null && (model?.isNotEmpty ?? false)) { - _search += "&model=$model"; - } - - if (expectedDateFrom != null) { - _search += "&expected_date_from=${(expectedDateFrom?.millisecondsSinceEpoch ?? 0) ~/ 1000}"; - } - - if (expectedDateTo != null) { - _search += "&expected_date_to=${(expectedDateTo?.millisecondsSinceEpoch ?? 0) ~/ 1000}"; - } - - if (actualDateFrom != null) { - _search += "&actual_date_from=${(actualDateFrom?.millisecondsSinceEpoch ?? 0) ~/ 1000}"; - } - - if (actualDateTo != null) { - _search += "&actual_date_to=${(actualDateTo?.millisecondsSinceEpoch ?? 0) ~/ 1000}"; - } - - if (statusValue != null) { - _search += "&status=$statusValue"; - } - - if (contactStatus != null) { - _search += "&assigned_to=$contactStatus"; - } - return _search; + Map queryParameters() { + return { + if (deviceSerialNumber != null && (deviceSerialNumber?.isNotEmpty ?? false)) 'sn_id': deviceSerialNumber, + if (statusValue != null) 'status': statusValue?.toString(), + if (hospitalName != null && (hospitalName?.isNotEmpty ?? false)) 'client': hospitalName, + if (brand != null && (brand?.isNotEmpty ?? false)) 'brand': brand, + if (model != null && (model?.isNotEmpty ?? false)) 'model': model, + if (expectedDateFrom != null) 'expected_date_from': (expectedDateFrom?.millisecondsSinceEpoch ?? 0) ~/ 1000, + if (expectedDateTo != null) 'expected_date_to': (expectedDateTo?.millisecondsSinceEpoch ?? 0) ~/ 1000, + if (actualDateFrom != null) 'actual_date_from': (actualDateFrom?.millisecondsSinceEpoch ?? 0) ~/ 1000, + if (actualDateTo != null) 'actual_date_to': (actualDateTo?.millisecondsSinceEpoch ?? 0) ~/ 1000, + if (contactStatus != null) 'assigned_to': contactStatus, + }; } } diff --git a/lib/views/pages/user/report_issues_page.dart b/lib/views/pages/user/report_issues_page.dart index f8316da1..f027f915 100644 --- a/lib/views/pages/user/report_issues_page.dart +++ b/lib/views/pages/user/report_issues_page.dart @@ -131,7 +131,7 @@ class ReportIssuesPageState extends State { if (_formKey.currentState?.validate() ?? false) { _issue.serviceRequestId = widget.serviceRequest?.id; _formKey.currentState?.save(); - _serviceRequestsProvider.createIssueReport(context, issue: _issue); + await _serviceRequestsProvider.createIssueReport(context, issue: _issue); } }, ), diff --git a/lib/views/pages/user/requests/report/create_service_report.dart b/lib/views/pages/user/requests/report/create_service_report.dart index 39cfa868..e37a8f95 100644 --- a/lib/views/pages/user/requests/report/create_service_report.dart +++ b/lib/views/pages/user/requests/report/create_service_report.dart @@ -664,7 +664,7 @@ class CreateServiceReportState extends State with TickerPro _validate = true; if (_formKey.currentState?.validate() ?? false) { _formKey.currentState?.save(); - _serviceRequestsProvider?.createServiceReport(context, report: _serviceReport, request: widget.request); + await _serviceRequestsProvider?.createServiceReport(context, report: _serviceReport, request: widget.request); } }, ), diff --git a/lib/views/pages/user/requests/report/edit_service_report.dart b/lib/views/pages/user/requests/report/edit_service_report.dart index 39719ab8..90a7113a 100644 --- a/lib/views/pages/user/requests/report/edit_service_report.dart +++ b/lib/views/pages/user/requests/report/edit_service_report.dart @@ -574,7 +574,7 @@ class EditServiceReportState extends State with TickerProvide _validate = true; if (_formKey.currentState?.validate() ?? false) { _formKey.currentState?.save(); - _serviceRequestsProvider.updateServiceReport(context, report: _serviceReport, request: widget.request); + await _serviceRequestsProvider.updateServiceReport(context, report: _serviceReport, request: widget.request); } }, ), diff --git a/lib/views/pages/user/requests/request_details.dart b/lib/views/pages/user/requests/request_details.dart index 39972013..8c783354 100644 --- a/lib/views/pages/user/requests/request_details.dart +++ b/lib/views/pages/user/requests/request_details.dart @@ -192,7 +192,7 @@ class RequestDetailsPage extends StatelessWidget { child: AButton( text: subtitle?.duplicateRequest ?? '', onPressed: () async { - serviceRequestsProvider.createDuplicatedReport(context, request: serviceRequest); + await serviceRequestsProvider.createDuplicatedReport(context, request: serviceRequest); }, ), ), diff --git a/lib/views/pages/user/requests/requests_page.dart b/lib/views/pages/user/requests/requests_page.dart index 96f6a207..30731d4e 100644 --- a/lib/views/pages/user/requests/requests_page.dart +++ b/lib/views/pages/user/requests/requests_page.dart @@ -43,7 +43,7 @@ class ServiceRequestsPageState extends State with TickerPro stateCode: _serviceRequestsProvider.stateCode, onRefresh: () async { _serviceRequestsProvider.reset(); - _serviceRequestsProvider.getRequests(); + await _serviceRequestsProvider.getRequests(); }, child: Stack( children: [ @@ -97,9 +97,9 @@ class ServiceRequestsPageState extends State with TickerPro ), Expanded( child: ServiceRequestsList( - nextPage: _serviceRequestsProvider.nextPage!, + nextPage: _serviceRequestsProvider.nextPage ?? false, onLazyLoad: () async { - _serviceRequestsProvider.getRequests(); + await _serviceRequestsProvider.getRequests(); }, requests: ServiceRequestApiClient().serviceRequests, ), diff --git a/lib/views/pages/user/visits/pantry/edit_pentry.dart b/lib/views/pages/user/visits/pantry/edit_pentry.dart index e3cf1ca4..7d35f375 100644 --- a/lib/views/pages/user/visits/pantry/edit_pentry.dart +++ b/lib/views/pages/user/visits/pantry/edit_pentry.dart @@ -1,12 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; -import '../../../../../api/user_api_client.dart'; -import '../../../../../controllers/http_status_manger/http_status_manger.dart'; import '../../../../../controllers/localization/localization.dart'; import '../../../../../controllers/providers/api/regular_visits_provider.dart'; -import '../../../../../controllers/providers/settings/setting_provider.dart'; import '../../../../../models/pantry/pentry.dart'; import '../../../../../models/subtitle.dart'; import '../../../../../models/visits/visit.dart'; @@ -28,45 +24,14 @@ class EditPentry extends StatefulWidget { } class _EditPentryState extends State with SingleTickerProviderStateMixin { - bool _isLoading = false; bool _validate = false; Subtitle? _subtitle; - late SettingProvider _settingProvider; late RegularVisitsProvider _regularVisitsProvider; Pentry? _pentry; final GlobalKey _scaffoldKey = GlobalKey(); late final TabController _tabController; - _onSubmit() async { - _validate = true; - - if (!(_pentry?.validate() ?? false)) { - setState(() {}); - return; - } - - _isLoading = true; - setState(() {}); - - int status = await _regularVisitsProvider.updatePentry(user: UserApiClient().user, host: _settingProvider.host, pentry: _pentry, visit: widget.visit); - _isLoading = false; - setState(() {}); - if (status >= 200 && status < 300) { - if (_subtitle != null) { - Fluttertoast.showToast( - msg: _subtitle!.requestCompleteSuccessfully, - ); - } - // Navigator.of(context).pop(); - } else { - String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle); - Fluttertoast.showToast( - msg: errorMessage, - ); - } - } - @override void initState() { _pentry = widget.pentry; @@ -83,13 +48,12 @@ class _EditPentryState extends State with SingleTickerProviderStateM @override Widget build(BuildContext context) { _subtitle = AppLocalization.of(context)?.subtitle; - _settingProvider = Provider.of(context); _regularVisitsProvider = Provider.of(context); return Scaffold( key: _scaffoldKey, body: SafeArea( child: LoadingManager( - isLoading: _isLoading, + isLoading: _regularVisitsProvider.loading, isFailedLoading: false, stateCode: 200, onRefresh: () async {}, @@ -176,7 +140,12 @@ class _EditPentryState extends State with SingleTickerProviderStateM if (_tabController.index == _tabController.length - 1) ASmallButton( text: _subtitle?.update, - onPressed: _onSubmit, + onPressed: () async { + _validate = true; + if (_pentry?.validate() ?? false) { + _regularVisitsProvider.updatePentry(context, pentry: _pentry, visit: widget.visit); + } + }, ), ], ), diff --git a/lib/views/pages/user/visits/pantry/future_edit_pently.dart b/lib/views/pages/user/visits/pantry/future_edit_pently.dart index f37ebf57..63dd6526 100644 --- a/lib/views/pages/user/visits/pantry/future_edit_pently.dart +++ b/lib/views/pages/user/visits/pantry/future_edit_pently.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import '../../../../../api/user_api_client.dart'; import '../../../../../controllers/localization/localization.dart'; import '../../../../../controllers/providers/api/regular_visits_provider.dart'; import '../../../../../controllers/providers/settings/setting_provider.dart'; @@ -23,6 +22,7 @@ class FutureEditPentry extends StatefulWidget { class _FutureEditPentryState extends State { late SettingProvider _settingProvider; + @override Widget build(BuildContext context) { _settingProvider = Provider.of(context); @@ -30,7 +30,7 @@ class _FutureEditPentryState extends State { Subtitle subtitle = AppLocalization.of(context)!.subtitle!; return Scaffold( body: FutureBuilder( - future: RegularVisitsProvider().getPently(user: UserApiClient().user!, host: _settingProvider.host ?? "", id: widget.visit.id!), + future: RegularVisitsProvider().getPently(id: widget.visit.id), builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.hasError) { return FailedLoading( diff --git a/lib/views/pages/user/visits/preventive_maintenance_visits_page.dart b/lib/views/pages/user/visits/preventive_maintenance_visits_page.dart index f34c37dd..06cfcd52 100644 --- a/lib/views/pages/user/visits/preventive_maintenance_visits_page.dart +++ b/lib/views/pages/user/visits/preventive_maintenance_visits_page.dart @@ -1,16 +1,10 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; +import 'package:test_sa/api/preventive_maintenance_api_client.dart'; -import '../../../../api/user_api_client.dart'; -import '../../../../controllers/http_status_manger/http_status_manger.dart'; import '../../../../controllers/localization/localization.dart'; import '../../../../controllers/providers/api/preventive_maintenance_visits_provider.dart'; -import '../../../../controllers/providers/settings/setting_provider.dart'; -import '../../../../controllers/providers/user_provider.dart'; import '../../../../models/subtitle.dart'; -import '../../../../models/visits/visits_group.dart'; import '../../../../models/visits/visits_search.dart'; import '../../../app_style/colors.dart'; import '../../../widgets/buttons/app_back_button.dart'; @@ -19,40 +13,33 @@ import '../../../widgets/buttons/app_icon_button.dart'; import '../../../widgets/loaders/loading_manager.dart'; import '../../../widgets/search/visits_search_bar.dart'; import '../../../widgets/visits/visits_list.dart'; -import 'update_visits_group_sheet.dart'; class PreventiveMaintenanceVisitsPage extends StatefulWidget { - static final String id = "/preventive-maintenance-visits"; + static const String id = "/preventive-maintenance-visits"; + + const PreventiveMaintenanceVisitsPage({super.key}); + @override - _PreventiveMaintenanceVisitsPageState createState() => _PreventiveMaintenanceVisitsPageState(); + PreventiveMaintenanceVisitsPageState createState() => PreventiveMaintenanceVisitsPageState(); } -class _PreventiveMaintenanceVisitsPageState extends State with TickerProviderStateMixin { +class PreventiveMaintenanceVisitsPageState extends State with TickerProviderStateMixin { late PreventiveMaintenanceVisitsProvider _visitsProvider; - late UserProvider _userProvider; - late SettingProvider _settingProvider; - late Subtitle _subtitle; + Subtitle? _subtitle; @override Widget build(BuildContext context) { _visitsProvider = Provider.of(context); - _userProvider = Provider.of(context); - _settingProvider = Provider.of(context); - _subtitle = AppLocalization.of(context)!.subtitle!; + _subtitle = AppLocalization.of(context)?.subtitle; return Scaffold( body: SafeArea( child: LoadingManager( - isLoading: _visitsProvider.isLoading, - isFailedLoading: _visitsProvider.visits == null, + isLoading: _visitsProvider.loading, stateCode: _visitsProvider.stateCode, onRefresh: () async { //_visitsProvider.visitsSearch = VisitsSearch(); _visitsProvider.reset(); - await _visitsProvider.getVisits( - user: UserApiClient().user!, - host: _settingProvider.host ?? "", - //visitsSearch: _visitsSearch - ); + await _visitsProvider.getVisits(); }, child: Stack( children: [ @@ -65,12 +52,12 @@ class _PreventiveMaintenanceVisitsPageState extends State( - context: context, - barrierDismissible: false, - builder: (BuildContext context) { - return CupertinoAlertDialog( - title: Text(_subtitle.updatingDots), - content: Center(child: CircularProgressIndicator()), - ); - }, - ); - int status = await _visitsProvider.updateGroupOfVisits(user: UserApiClient().user!, host: _settingProvider.host ?? "", group: _group); - Navigator.of(context).pop(); - if (status >= 200 && status < 300) { - Fluttertoast.showToast( - msg: _subtitle.preventiveMaintenanceUpdatedSuccessfully, - toastLength: Toast.LENGTH_LONG, - gravity: ToastGravity.BOTTOM, - ); - } else { - Fluttertoast.showToast( - msg: HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle), - toastLength: Toast.LENGTH_LONG, - gravity: ToastGravity.BOTTOM, - ); - } - } + _visitsProvider.updateGroupOfVisits(context); }, - visits: _visitsProvider.visits!, + visits: PreventiveMaintenanceApiClient().visits, ), ), ], diff --git a/lib/views/pages/user/visits/regular_visits_page.dart b/lib/views/pages/user/visits/regular_visits_page.dart index 3eb96124..319931e4 100644 --- a/lib/views/pages/user/visits/regular_visits_page.dart +++ b/lib/views/pages/user/visits/regular_visits_page.dart @@ -1,16 +1,10 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:fluttertoast/fluttertoast.dart'; import 'package:provider/provider.dart'; +import 'package:test_sa/api/visits_api_client.dart'; -import '../../../../api/user_api_client.dart'; -import '../../../../controllers/http_status_manger/http_status_manger.dart'; import '../../../../controllers/localization/localization.dart'; import '../../../../controllers/providers/api/regular_visits_provider.dart'; -import '../../../../controllers/providers/settings/setting_provider.dart'; -import '../../../../controllers/providers/user_provider.dart'; import '../../../../models/subtitle.dart'; -import '../../../../models/visits/visits_group.dart'; import '../../../../models/visits/visits_search.dart'; import '../../../app_style/colors.dart'; import '../../../widgets/buttons/app_back_button.dart'; @@ -19,40 +13,34 @@ import '../../../widgets/buttons/app_icon_button.dart'; import '../../../widgets/loaders/loading_manager.dart'; import '../../../widgets/search/visits_search_bar.dart'; import '../../../widgets/visits/visits_list.dart'; -import 'update_visits_group_sheet.dart'; class RegularVisitsPage extends StatefulWidget { static const String id = "/Regular-visits"; const RegularVisitsPage({super.key}); + @override - _RegularVisitsPageState createState() => _RegularVisitsPageState(); + RegularVisitsPageState createState() => RegularVisitsPageState(); } -class _RegularVisitsPageState extends State with TickerProviderStateMixin { +class RegularVisitsPageState extends State with TickerProviderStateMixin { late RegularVisitsProvider _visitsProvider; - late UserProvider _userProvider; - late SettingProvider _settingProvider; - bool _expandedSearch = false; - late Subtitle _subtitle; + final bool _expandedSearch = false; + late Subtitle? _subtitle; + @override Widget build(BuildContext context) { _visitsProvider = Provider.of(context); - _settingProvider = Provider.of(context); - _userProvider = Provider.of(context); - _subtitle = AppLocalization.of(context)!.subtitle!; + _subtitle = AppLocalization.of(context)?.subtitle; return Scaffold( body: SafeArea( child: LoadingManager( - isLoading: _visitsProvider.isLoading, + isLoading: _visitsProvider.loading, stateCode: _visitsProvider.stateCode, onRefresh: () async { _visitsProvider.reset(); //_visitsProvider.visitsSearch = VisitsSearch(); - await _visitsProvider.getVisits( - user: UserApiClient().user, - host: _settingProvider.host, - ); + await _visitsProvider.getVisits(); }, child: Stack( children: [ @@ -65,17 +53,17 @@ class _RegularVisitsPageState extends State with TickerProvid children: [ Row( children: [ - ABackButton(), + const ABackButton(), Expanded( child: Center( child: Text( - _subtitle.preventiveMaintenance, - style: Theme.of(context).textTheme.headline6?.copyWith(color: AColors.white, fontStyle: FontStyle.italic), + _subtitle?.preventiveMaintenance ?? '', + style: Theme.of(context).textTheme.titleLarge?.copyWith(color: AColors.white, fontStyle: FontStyle.italic), ), ), ), AnimatedSwitcher( - duration: Duration(milliseconds: 400), + duration: const Duration(milliseconds: 400), child: AIconButton( key: ValueKey(_expandedSearch), iconData: _expandedSearch ? Icons.keyboard_arrow_up : Icons.search, @@ -83,35 +71,33 @@ class _RegularVisitsPageState extends State with TickerProvid buttonSize: 42, backgroundColor: AColors.white, onPressed: () async { - VisitsSearch _temp = await showModalBottomSheet( + VisitsSearch temp = await showModalBottomSheet( context: context, isScrollControlled: true, builder: (context) { return VisitsSearchDialog( initialSearchValue: _visitsProvider.visitsSearch!, - onSearch: (VisitsSearch) {}, + onSearch: (visitsSearch) {}, ); }); - _visitsProvider.visitsSearch?.fromSearch(_temp); + _visitsProvider.visitsSearch?.fromSearch(temp); _visitsProvider.reset(); setState(() {}); }, ), ), - SizedBox( - width: 16, - ) + const SizedBox(width: 16) ], ), ], ), ), Visibility( - visible: _visitsProvider.visitsSearch?.toSearchString().isNotEmpty ?? false, + visible: _visitsProvider.visitsSearch?.queryParameters().isNotEmpty ?? false, child: Padding( padding: const EdgeInsets.all(8.0), child: AButton( - text: _subtitle.clearSearch, + text: _subtitle?.clearSearch ?? '', onPressed: () { _visitsProvider.visitsSearch = VisitsSearch(); _visitsProvider.reset(); @@ -124,51 +110,12 @@ class _RegularVisitsPageState extends State with TickerProvid child: VisitsList( nextPage: _visitsProvider.nextPage, onLazyLoad: () async { - await _visitsProvider.getVisits( - user: UserApiClient().user!, - host: _settingProvider.host ?? "", - ); + await _visitsProvider.getVisits(); }, onEditGroup: (visits) async { - VisitsGroup? group = await showModalBottomSheet( - isScrollControlled: true, - context: context, - builder: (context) { - return UpdateVisitsGroupSheet( - visits: visits, - title: _subtitle.updateRegularVisits, - ); - }, - ) as VisitsGroup?; - if (group != null) { - showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext context) { - return CupertinoAlertDialog( - title: Text(_subtitle.updatingDots), - content: Center(child: CircularProgressIndicator()), - ); - }, - ); - int status = await _visitsProvider.updateGroupOfVisits(user: UserApiClient().user!, host: _settingProvider.host ?? "", group: group); - Navigator.of(context).pop(); - if (status >= 200 && status < 300) { - Fluttertoast.showToast( - msg: _subtitle.regularVisitsUpdatedSuccessfully, - toastLength: Toast.LENGTH_LONG, - gravity: ToastGravity.BOTTOM, - ); - } else { - Fluttertoast.showToast( - msg: HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle), - toastLength: Toast.LENGTH_LONG, - gravity: ToastGravity.BOTTOM, - ); - } - } + await _visitsProvider.updateGroupOfVisits(context); }, - visits: _visitsProvider.visits, + visits: VisitsApiClient().visits, ), ), ], diff --git a/lib/views/pages/user/visits/visit_details.dart b/lib/views/pages/user/visits/visit_details.dart index 360dcfad..156b7e8a 100644 --- a/lib/views/pages/user/visits/visit_details.dart +++ b/lib/views/pages/user/visits/visit_details.dart @@ -16,13 +16,13 @@ import '../../../widgets/visits/visit_status.dart'; import 'pantry/future_edit_pently.dart'; class VisitDetailsPage extends StatelessWidget { - static final String id = "/visit-details"; + static const String id = "/visit-details"; final Visit visit; const VisitDetailsPage({Key? key, required this.visit}) : super(key: key); @override Widget build(BuildContext context) { - Subtitle _subtitle = AppLocalization.of(context)!.subtitle!; + Subtitle subtitle = AppLocalization.of(context)!.subtitle!; final regularVisitsProvider = Provider.of(context); return Scaffold( @@ -38,7 +38,7 @@ class VisitDetailsPage extends StatelessWidget { Expanded( child: Center( child: Text( - _subtitle.visitInformation, + subtitle.visitInformation, style: Theme.of(context).textTheme.headline6?.copyWith(color: AColors.white, fontStyle: FontStyle.italic), ), ), @@ -105,7 +105,7 @@ class VisitDetailsPage extends StatelessWidget { height: 8, ), RequestInfoRow( - title: _subtitle.code, + title: subtitle.code, info: visit.serialNumber, ), RequestInfoRow( @@ -113,22 +113,22 @@ class VisitDetailsPage extends StatelessWidget { info: visit.deviceNumber, ), RequestInfoRow( - title: _subtitle.deviceSN, + title: subtitle.deviceSN, info: visit.deviceSerialNumber, ), RequestInfoRow( - title: _subtitle.expectDate, + title: subtitle.expectDate, info: visit.expectDate, ), RequestInfoRow( - title: _subtitle.actualDate, + title: subtitle.actualDate, info: visit.actualDate, ), Row( children: [ Expanded( child: Text( - "${_subtitle.status} : ", + "${subtitle.status} : ", style: Theme.of(context).textTheme.subtitle1?.copyWith(fontWeight: FontWeight.bold), textScaleFactor: AppStyle.getScaleFactor(context), ), @@ -142,23 +142,23 @@ class VisitDetailsPage extends StatelessWidget { color: Theme.of(context).primaryColor, ), RequestInfoRow( - title: _subtitle.contactStatus, + title: subtitle.contactStatus, info: visit.assignTo, ), RequestInfoRow( - title: _subtitle.engineerName, + title: subtitle.engineerName, info: visit.employName, ), RequestInfoRow( - title: _subtitle.hospital, + title: subtitle.hospital, content: visit.hospitalName, ), RequestInfoRow( - title: _subtitle.deviceArName, + title: subtitle.deviceArName, content: visit.deviceArabicName, ), RequestInfoRow( - title: _subtitle.deviceEnName, + title: subtitle.deviceEnName, content: visit.deviceEnglishName, ), ], diff --git a/lib/views/widgets/loaders/lazy_loading.dart b/lib/views/widgets/loaders/lazy_loading.dart index d91b7af9..d3f692b1 100644 --- a/lib/views/widgets/loaders/lazy_loading.dart +++ b/lib/views/widgets/loaders/lazy_loading.dart @@ -18,21 +18,21 @@ class LazyLoading extends StatefulWidget { }) : super(key: key); @override - _LazyLoadingState createState() => _LazyLoadingState(); + LazyLoadingState createState() => LazyLoadingState(); } -class _LazyLoadingState extends State with TickerProviderStateMixin { +class LazyLoadingState extends State with TickerProviderStateMixin { late AnimationController _animationController; late Animation _offsetAnimation; _scrollListener() async { if (!_animationController.isAnimating && !_animationController.isCompleted && widget.nextPage) { - _animationController?.forward(); + _animationController.forward(); setState(() {}); await widget.onLazyLoad(); - await Future.delayed(Duration(milliseconds: 600)); + await Future.delayed(const Duration(milliseconds: 600)); setState(() {}); - _animationController?.reverse(); + _animationController.reverse(); } } @@ -56,7 +56,7 @@ class _LazyLoadingState extends State with TickerProviderStateMixin @override void dispose() { super.dispose(); - _animationController?.dispose(); + _animationController.dispose(); } @override @@ -75,13 +75,13 @@ class _LazyLoadingState extends State with TickerProviderStateMixin position: _offsetAnimation, child: Center( child: Visibility( - visible: (_animationController?.isAnimating ?? false) || (_animationController?.isCompleted ?? false), + visible: (_animationController.isAnimating) || (_animationController.isCompleted), child: Container( height: 36 * AppStyle.getScaleFactor(context), width: 36 * AppStyle.getScaleFactor(context), - padding: EdgeInsets.all(8), - decoration: BoxDecoration(color: Colors.white, shape: BoxShape.circle, boxShadow: [AppStyle.boxShadow]), - child: ALoading(), + padding: const EdgeInsets.all(8), + decoration: const BoxDecoration(color: Colors.white, shape: BoxShape.circle, boxShadow: [AppStyle.boxShadow]), + child: const ALoading(), ), ), ), diff --git a/lib/views/widgets/loaders/loading_manager.dart b/lib/views/widgets/loaders/loading_manager.dart index 67c1c01f..b88ca5ac 100644 --- a/lib/views/widgets/loaders/loading_manager.dart +++ b/lib/views/widgets/loaders/loading_manager.dart @@ -49,7 +49,7 @@ class _LoadingManagerState extends State { Subtitle? subtitle = AppLocalization.of(context)?.subtitle; Widget? placeHolder; // to load data if load not start - if (widget.isLoading == false && widget.stateCode == null) { + if (widget.onRefresh != null && widget.isLoading == false && widget.stateCode == null) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) { widget.onRefresh!(); }); @@ -70,7 +70,7 @@ class _LoadingManagerState extends State { // if load end successfully return loaded widget return RefreshIndicator( onRefresh: () async { - await widget.onRefresh!(); + if (widget.onRefresh != null) await widget.onRefresh!(); }, child: AnimatedSwitcher( duration: const Duration(milliseconds: 400), diff --git a/lib/views/widgets/requests/service_request_update_dialog.dart b/lib/views/widgets/requests/service_request_update_dialog.dart index 5258ffdb..7e65f1a0 100644 --- a/lib/views/widgets/requests/service_request_update_dialog.dart +++ b/lib/views/widgets/requests/service_request_update_dialog.dart @@ -63,12 +63,12 @@ class _ServiceRequestsUpdateDialogState extends State with TickerProvi }, ), Visibility( - visible: _search?.toSearchString().isNotEmpty ?? false, + visible: _search?.queryParameters().isNotEmpty ?? false, child: Padding( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), child: AButton(