Track Service Filter DONE && Preventive Maintenance DONE

merge-requests/14/head
zaid_daoud 2 years ago
parent 802ec7bb01
commit 3a20bf0017

@ -66,7 +66,7 @@ class ApiClient {
factory ApiClient() => _instance;
Future<U> postJsonForObject<T, U>(FactoryConstructor<U> factoryConstructor, String url, T jsonObject,
{String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0, bool isFormData = false}) async {
{String? token, Map<String, dynamic>? queryParameters, Map<String, String>? 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<Response> postJsonForResponse<T>(String url, T jsonObject,
{String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0, bool isFormData = false}) async {
{String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0, bool isFormData = true}) async {
int currentRetryTime = retryTimes;
String? requestBody;
late Map<String, String> stringObj;

@ -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<Visit> 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<Visit> visitsList = requestsListJson.map((request) => Visit.fromJson(request)).toList();
visits.addAll(visitsList);
}
Future updateGroupOfVisits({required VisitsGroup group}) async {
final user = UserApiClient().user;
Map<String, String> 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();
}
}

@ -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<String, String> 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<ServiceReport> getSingleServiceReport({required String reportId}) async {

@ -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<String, dynamic> jsonObject = {};
// jsonObject["uid"] = user.id;

@ -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<Visit> 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<Visit> visitsList = requestsListJson.map((request) => Visit.fromJson(request)).toList();
visits.addAll(visitsList);
}
Future updateGroupOfVisits({required VisitsGroup group}) async {
final user = UserApiClient().user;
Map<String, String> 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<Pentry> 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<String, String>? 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;
}
}

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

@ -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<Visit>? 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<int> 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<Visit> 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<int> updateGroupOfVisits({
required String host,
required User user,
required VisitsGroup group,
}) async {
Response response;
Map<String, String> 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<void>(
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;
}
}
}

@ -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<Visit> 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<int> 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<Visit> 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<int> updateGroupOfVisits({
required String host,
required User user,
required VisitsGroup group,
}) async {
Response response;
Map<String, String> 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<void>(
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<Pentry?> 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<Pentry?> getPently({required String? id}) async {
return id == null ? null : await VisitsApiClient().getPentry(id);
}
Future<int> updatePentry({
required String? host,
required User? user,
required Pentry? pentry,
required Visit? visit,
}) async {
try {
Response response;
Map<String, String>? 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);
},
);
}
}

@ -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<void>(
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();

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

@ -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<String, dynamic> queryParameters() {
return <String, dynamic>{
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,
};
}
}

@ -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<String, dynamic> queryParameters() {
return <String, dynamic>{
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,
};
}
}

@ -131,7 +131,7 @@ class ReportIssuesPageState extends State<ReportIssuesPage> {
if (_formKey.currentState?.validate() ?? false) {
_issue.serviceRequestId = widget.serviceRequest?.id;
_formKey.currentState?.save();
_serviceRequestsProvider.createIssueReport(context, issue: _issue);
await _serviceRequestsProvider.createIssueReport(context, issue: _issue);
}
},
),

@ -664,7 +664,7 @@ class CreateServiceReportState extends State<CreateServiceReport> 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);
}
},
),

@ -574,7 +574,7 @@ class EditServiceReportState extends State<EditServiceReport> 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);
}
},
),

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

@ -43,7 +43,7 @@ class ServiceRequestsPageState extends State<ServiceRequestsPage> 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<ServiceRequestsPage> with TickerPro
),
Expanded(
child: ServiceRequestsList(
nextPage: _serviceRequestsProvider.nextPage!,
nextPage: _serviceRequestsProvider.nextPage ?? false,
onLazyLoad: () async {
_serviceRequestsProvider.getRequests();
await _serviceRequestsProvider.getRequests();
},
requests: ServiceRequestApiClient().serviceRequests,
),

@ -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<EditPentry> with SingleTickerProviderStateMixin {
bool _isLoading = false;
bool _validate = false;
Subtitle? _subtitle;
late SettingProvider _settingProvider;
late RegularVisitsProvider _regularVisitsProvider;
Pentry? _pentry;
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
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<EditPentry> with SingleTickerProviderStateM
@override
Widget build(BuildContext context) {
_subtitle = AppLocalization.of(context)?.subtitle;
_settingProvider = Provider.of<SettingProvider>(context);
_regularVisitsProvider = Provider.of<RegularVisitsProvider>(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<EditPentry> 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);
}
},
),
],
),

@ -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<FutureEditPentry> {
late SettingProvider _settingProvider;
@override
Widget build(BuildContext context) {
_settingProvider = Provider.of<SettingProvider>(context);
@ -30,7 +30,7 @@ class _FutureEditPentryState extends State<FutureEditPentry> {
Subtitle subtitle = AppLocalization.of(context)!.subtitle!;
return Scaffold(
body: FutureBuilder<Pentry?>(
future: RegularVisitsProvider().getPently(user: UserApiClient().user!, host: _settingProvider.host ?? "", id: widget.visit.id!),
future: RegularVisitsProvider().getPently(id: widget.visit.id),
builder: (BuildContext context, AsyncSnapshot<Pentry?> snapshot) {
if (snapshot.hasError) {
return FailedLoading(

@ -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<PreventiveMaintenanceVisitsPage> with TickerProviderStateMixin {
class PreventiveMaintenanceVisitsPageState extends State<PreventiveMaintenanceVisitsPage> with TickerProviderStateMixin {
late PreventiveMaintenanceVisitsProvider _visitsProvider;
late UserProvider _userProvider;
late SettingProvider _settingProvider;
late Subtitle _subtitle;
Subtitle? _subtitle;
@override
Widget build(BuildContext context) {
_visitsProvider = Provider.of<PreventiveMaintenanceVisitsProvider>(context);
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(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<PreventiveMaintenanceV
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),
),
),
),
@ -80,41 +67,35 @@ class _PreventiveMaintenanceVisitsPageState extends State<PreventiveMaintenanceV
buttonSize: 42,
backgroundColor: AColors.white,
onPressed: () async {
VisitsSearch? _temp = await showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) {
return VisitsSearchDialog(
initialSearchValue: _visitsProvider.visitsSearch!,
onSearch: (VisitsSearch) {},
);
});
if (_temp != null) {
_visitsProvider.visitsSearch = _temp;
VisitsSearch? temp = await showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) {
return VisitsSearchDialog(
initialSearchValue: _visitsProvider.visitsSearch!,
onSearch: (visitsSearch) {},
);
},
);
if (temp != null) {
_visitsProvider.visitsSearch = temp;
_visitsProvider.reset();
setState(() {});
await _visitsProvider.getVisits(
user: UserApiClient().user!,
host: _settingProvider.host ?? "",
//visitsSearch: _visitsSearch
);
await _visitsProvider.getVisits();
}
},
),
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();
@ -127,52 +108,12 @@ class _PreventiveMaintenanceVisitsPageState extends State<PreventiveMaintenanceV
child: VisitsList(
nextPage: _visitsProvider.nextPage!,
onLazyLoad: () async {
await _visitsProvider.getVisits(
user: UserApiClient().user!,
host: _settingProvider.host ?? "",
//visitsSearch: _visitsSearch
);
await _visitsProvider.getVisits();
},
onEditGroup: (visits) async {
VisitsGroup _group = await showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (context) {
return UpdateVisitsGroupSheet(
visits: visits,
title: _subtitle.updatePreventiveMaintenance,
);
},
) as VisitsGroup;
if (_group != null) {
showDialog<void>(
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,
),
),
],

@ -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<RegularVisitsPage> with TickerProviderStateMixin {
class RegularVisitsPageState extends State<RegularVisitsPage> 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<RegularVisitsProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context);
_userProvider = Provider.of<UserProvider>(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<RegularVisitsPage> 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<RegularVisitsPage> 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<RegularVisitsPage> 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<void>(
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,
),
),
],

@ -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<RegularVisitsProvider>(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,
),
],

@ -18,21 +18,21 @@ class LazyLoading extends StatefulWidget {
}) : super(key: key);
@override
_LazyLoadingState createState() => _LazyLoadingState();
LazyLoadingState createState() => LazyLoadingState();
}
class _LazyLoadingState extends State<LazyLoading> with TickerProviderStateMixin {
class LazyLoadingState extends State<LazyLoading> with TickerProviderStateMixin {
late AnimationController _animationController;
late Animation<Offset> _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<LazyLoading> with TickerProviderStateMixin
@override
void dispose() {
super.dispose();
_animationController?.dispose();
_animationController.dispose();
}
@override
@ -75,13 +75,13 @@ class _LazyLoadingState extends State<LazyLoading> 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(),
),
),
),

@ -49,7 +49,7 @@ class _LoadingManagerState extends State<LoadingManager> {
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<LoadingManager> {
// 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),

@ -63,12 +63,12 @@ class _ServiceRequestsUpdateDialogState extends State<ServiceRequestsUpdateDialo
),
ASmallButton(
text: _subtitle?.update,
onPressed: () {
onPressed: () async {
if (_dateTime == null && _employee == null) {
Fluttertoast.showToast(msg: _subtitle?.noDateFound ?? '');
return;
}
_serviceRequestsProvider?.updateDate(context, request: widget.request, newDate: _dateTime?.toString().split(" ").first, employee: _employee);
await _serviceRequestsProvider?.updateDate(context, request: widget.request, newDate: _dateTime?.toString().split(" ").first, employee: _employee);
},
)
],

@ -170,7 +170,7 @@ class ServiceRequestsSearchDialogState extends State<ServiceRequestsSearchDialog
),
),
Visibility(
visible: widget.initialSearchValue.toSearchString().isNotEmpty,
visible: widget.initialSearchValue.queryParameters().isNotEmpty,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 8,

@ -245,7 +245,7 @@ class VisitsSearchDialogState extends State<VisitsSearchDialog> 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(

Loading…
Cancel
Save