Track Service Request DONE

merge-requests/14/head
zaid_daoud 3 years ago
parent 5f78d7e164
commit 802ec7bb01

@ -2,7 +2,12 @@ import 'dart:convert';
import 'package:test_sa/api/api_client.dart';
import 'package:test_sa/api/user_api_client.dart';
import 'package:test_sa/models/issue.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/service_report.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/models/service_request/service_request_search.dart';
import 'package:test_sa/models/timer_model.dart';
import '../controllers/api_routes/urls.dart';
@ -38,4 +43,104 @@ class ServiceRequestApiClient {
isFormData: true,
);
}
/// Get Service Requests and Fill [serviceRequests]
Future<List<ServiceRequest>> getRequests({pageItemNumber, ServiceRequestSearch? search}) async {
final user = UserApiClient().user;
final response = await ApiClient().getJsonForResponse(
'${URLs.host1}${URLs.getServiceRequests}',
headers: {"Content-Type": "application/json; charset=utf-8"},
queryParameters: {
'uid': user?.id,
if (user?.hospital?.id != null) 'client_nid': user?.hospital?.id,
'token': user?.token,
'page': '${(serviceRequests.length) ~/ pageItemNumber}${search?.toSearchString()}',
},
);
List requestsListJson = json.decode(utf8.decode(response.bodyBytes));
List<ServiceRequest> serviceRequestsPage = requestsListJson.map((request) => ServiceRequest.fromJson(request)).toList();
serviceRequests.addAll(serviceRequestsPage);
return serviceRequestsPage;
}
Future<ServiceRequest> getServiceById(String? requestId) async {
final user = UserApiClient().user;
final response = await ApiClient().getJsonForResponse(
'${URLs.host1}${URLs.getSingleServiceRequest}',
queryParameters: {'call_nid': requestId, 'uid': user?.id, 'token': user?.token},
);
// If the call to the server was successful, parse the JSON.
List jsonList = json.decode(utf8.decode(response.bodyBytes));
List<ServiceRequest> requests = jsonList.map((i) => ServiceRequest.fromJson(i)).toList();
return requests[0];
}
Future createIssueReport(Issue issue) async {
final user = UserApiClient().user;
Map<String, String> body = issue.toMap();
body["uid"] = user?.id ?? "";
body["token"] = user?.token ?? "";
await ApiClient().postJsonForResponse('${URLs.host1}${URLs.createReport}', body, isFormData: true);
}
Future updateDate({String? newDate, Lookup? employee, ServiceRequest? request}) async {
final user = UserApiClient().user;
Map<String, String> body = {};
body["uid"] = user?.id ?? '';
body["token"] = user?.token ?? '';
body["nid"] = request?.id ?? '';
body["date"] = newDate ?? '';
body["ass_emp"] = employee?.id?.toString() ?? '';
await ApiClient().postJsonForResponse('${URLs.host1}${URLs.updateRequestDate}', body, isFormData: true);
request?.engineerName = employee?.label;
}
Future createServiceReport({required ServiceReport? report, required ServiceRequest? request}) async {
final user = UserApiClient().user;
Map<String, String>? body = report?.toMap();
body?["uid"] = user?.id ?? "";
body?["token"] = user?.token ?? "";
body?["job_id"] = request?.id ?? '';
await ApiClient().postJsonForResponse('${URLs.host1}${URLs.createServiceReport}', body, isFormData: true);
}
Future createDuplicatedReport({required ServiceRequest request}) async {
final user = UserApiClient().user;
await ApiClient().getJsonForResponse(
'${URLs.host1}${URLs.createDuplicatedReport}',
queryParameters: {'nid': request.id, 'uid': user?.id, 'token': user?.token},
);
}
Future updateServiceReport({required ServiceReport report, required ServiceRequest request}) async {
final user = UserApiClient().user;
Map<String, String> body = report.toMap();
body["uid"] = user?.id ?? "";
body["token"] = user?.token ?? "";
body["job_id"] = request.id ?? '';
body["report_id"] = request.reportID ?? '';
await ApiClient().postJsonForResponse('${URLs.host1}${URLs.updateServiceReport}', body, isFormData: true);
}
Future updateServiceReportTimer({required TimerModel timer, required ServiceRequest request}) async {
final user = UserApiClient().user;
Map<String, String> body = {};
body["uid"] = user?.id ?? "";
body["token"] = user?.token ?? "";
body["job_id"] = request.id ?? '';
body["start_time"] = ((timer.startAt?.millisecondsSinceEpoch ?? 0) / 1000).toStringAsFixed(0);
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);
}
Future<ServiceReport> getSingleServiceReport({required String reportId}) async {
final user = UserApiClient().user;
final response = await ApiClient().getJsonForResponse(
'${URLs.host1}${URLs.getServiceReport}',
queryParameters: {'report_id': reportId, 'uid': user?.id, 'token': user?.token},
);
return ServiceReport.fromJson(json.decode(utf8.decode(response.bodyBytes)), reportId);
}
}

@ -1,21 +1,20 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:http/http.dart';
import 'package:test_sa/api/service_request_api_client.dart';
import 'package:test_sa/controllers/providers/loading_notifier.dart';
import 'package:test_sa/exceptions/api_exception.dart';
import '../../../models/issue.dart';
import '../../../models/lookup.dart';
import '../../../models/service_report.dart';
import '../../../models/service_request/service_request.dart';
import '../../../models/service_request/service_request_search.dart';
import '../../../models/subtitle.dart';
import '../../../models/timer_model.dart';
import '../../../models/user.dart';
import '../../api_routes/urls.dart';
import '../../../views/widgets/dialogs/dialog.dart';
import '../../http_status_manger/http_status_manger.dart';
import '../../localization/localization.dart';
@ -38,86 +37,28 @@ class ServiceRequestsProvider extends LoadingNotifier {
// true if there is next page in product list and false if not
bool? nextPage = true;
// when requests in-process _loading = true
// done _loading = true
// failed _loading = false
bool? isLoading;
ServiceRequestSearch? search = ServiceRequestSearch();
/// 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> getRequests({
required String host,
required User? user,
required String? hospitalId,
}) async {
if (isLoading == true) {
return -2;
}
isLoading = true;
Response response;
try {
response = await get(
Uri.parse(
"$host${URLs.getServiceRequests}?uid=${user?.id}${hospitalId == null ? "" : "&client_nid=$hospitalId"}&token=${user?.token}&page=${(ServiceRequestApiClient().serviceRequests.length) ~/ pageItemNumber}${search?.toSearchString()}",
),
headers: {"Content-Type": "application/json; charset=utf-8"},
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
// client's request was successfully received
List requestsListJson = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", ""));
List<ServiceRequest> serviceRequestsPage = requestsListJson.map((request) => ServiceRequest.fromJson(request)).toList();
ServiceRequestApiClient().serviceRequests.addAll(serviceRequestsPage);
if (serviceRequestsPage.length == pageItemNumber) {
nextPage = true;
} else {
nextPage = false;
}
/// Get Service Requests and Fill [ServiceRequestApiClient.serviceRequests]
void getRequests() async {
waitApiRequest(() async {
final serviceRequestsPage = await ServiceRequestApiClient().getRequests(pageItemNumber: pageItemNumber, search: search);
if (serviceRequestsPage.length == pageItemNumber) {
nextPage = true;
} else {
nextPage = false;
}
isLoading = false;
notifyListeners();
return response.statusCode;
} catch (error) {
isLoading = false;
stateCode = -1;
notifyListeners();
return -1;
}
}, onSuccess: () {
/// TODO : this is temporary
stateCode = 200;
}, onError: (error) {
/// TODO : this is temporary
stateCode = error.error?.errorCode;
});
}
Future<ServiceRequest> getSingleServiceRequest({
required String requestId,
required String host,
required User user,
required Subtitle subtitle,
}) async {
String userData = '';
userData += "&uid=${user.id}";
userData += "&token=${user.token}";
Response response;
try {
response = await get(Uri.parse(
'$host${URLs.getSingleServiceRequest}?call_nid=$requestId$userData',
));
} catch (error) {
throw (HttpStatusManger.getStatusMessage(status: -1, subtitle: subtitle) ?? '');
}
// If the call to the server was successful, parse the JSON.
if (response.statusCode >= 200 && response.statusCode < 300) {
// If the call to the server was successful, parse the JSON.
List jsonList = json.decode(utf8.decode(response.bodyBytes).replaceAll("\\", ""));
List<ServiceRequest> requests = jsonList.map((i) => ServiceRequest.fromJson(i)).toList();
return requests[0];
} else {
throw (HttpStatusManger.getStatusMessage(status: response.statusCode, subtitle: subtitle));
}
Future<ServiceRequest> getSingleServiceRequest({required String? requestId}) async {
return await ServiceRequestApiClient().getServiceById(requestId);
}
/// ### Create service request and add the response to [ServiceRequestApiClient.serviceRequests]
@ -145,206 +86,136 @@ class ServiceRequestsProvider extends LoadingNotifier {
});
}
Future<int> createIssueReport({
required String host,
required User user,
required Issue issue,
}) async {
Response response;
Map<String, String> body = issue.toMap();
body["uid"] = user.id ?? "";
body["token"] = user.token ?? "";
try {
response = await post(
Uri.parse(host + URLs.createReport),
body: body,
);
void createIssueReport(BuildContext context, {required Issue issue}) async {
waitApiRequest(() async {
await ServiceRequestApiClient().createIssueReport(issue);
}, onSuccess: () {
final subtitle = AppLocalization.of(context)?.subtitle;
Fluttertoast.showToast(msg: subtitle?.requestCompleteSuccessfully ?? '');
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {}
return response.statusCode;
} catch (error) {
return -1;
}
/// TODO : this is temporary
stateCode = 200;
}, onError: (error) {
/// TODO : this is temporary
stateCode = error.error?.errorCode;
});
}
Future<int> updateDate({
required String? host,
required User? user,
required String? newDate,
required Lookup? employee,
required ServiceRequest? request,
}) async {
Response response;
Map<String, String> body = {};
body["uid"] = user?.id ?? '';
body["token"] = user?.token ?? '';
body["nid"] = request?.id ?? '';
body["date"] = newDate ?? '';
body["ass_emp"] = employee?.id.toString() ?? '';
try {
response = await post(
Uri.parse((host ?? '') + URLs.updateRequestDate),
body: body,
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
request?.engineerName = employee?.label;
notifyListeners();
}
return response.statusCode;
} catch (error) {
return -1;
}
void updateDate(BuildContext context, {required String? newDate, required Lookup? employee, required ServiceRequest? request}) {
final subtitle = AppLocalization.of(context)?.subtitle;
showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return CupertinoAlertDialog(title: Text(subtitle?.updatingDots ?? ''), content: const Center(child: CircularProgressIndicator()));
},
);
waitApiRequest(
() async {
await ServiceRequestApiClient().updateDate(newDate: newDate, employee: employee, request: request);
},
onSuccess: () {
Navigator.of(context).pop();
Fluttertoast.showToast(msg: HttpStatusManger.getStatusMessage(status: 200, subtitle: subtitle));
/// TODO : this is temporary
stateCode = 200;
},
onError: (error) {
/// TODO : this is temporary
stateCode = error.error?.errorCode;
},
);
}
Future<int> createServiceReport({
required String host,
required User user,
required ServiceReport report,
required ServiceRequest request,
}) async {
Response response;
Map<String, String> body = report.toMap();
body["uid"] = user.id ?? "";
body["token"] = user.token ?? "";
body["job_id"] = request.id ?? '';
try {
response = await post(
Uri.parse(host + URLs.createServiceReport),
body: body,
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
void createServiceReport(BuildContext context, {required ServiceReport? report, required ServiceRequest? request}) async {
final subtitle = AppLocalization.of(context)?.subtitle;
waitApiRequest(
() async {
await ServiceRequestApiClient().createServiceReport(report: report, request: request);
reset();
notifyListeners();
}
return response.statusCode;
} catch (error) {
return -1;
}
},
onSuccess: () {
/// TODO : this is temporary
stateCode = 200;
Fluttertoast.showToast(msg: subtitle?.requestCompleteSuccessfully ?? "");
Navigator.of(context).pop();
Navigator.of(context).pop();
},
onError: (error) {
/// TODO : this is temporary
stateCode = error.error?.errorCode;
String errorMessage = HttpStatusManger.getStatusMessage(status: error.error?.errorCode, subtitle: subtitle);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(errorMessage)));
},
);
}
Future<int> createDuplicatedReport({
required String host,
required User user,
required ServiceRequest request,
}) async {
Response response;
String userData = '';
userData += "&uid=${user.id}";
userData += "&token=${user.token}";
try {
response = await get(
Uri.parse(
"$host${URLs.createDuplicatedReport}?nid=${request.id}$userData",
),
void 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) {
showDialog(
context: context,
builder: (context) {
return const Center(child: CircularProgressIndicator());
},
);
waitApiRequest(
() async {
await ServiceRequestApiClient().createDuplicatedReport(request: request);
reset();
},
onSuccess: () {
Navigator.of(context).pop();
},
onError: (error) {
/// TODO : this is temporary
stateCode = error.error?.errorCode;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(HttpStatusManger.getStatusMessage(status: error.error?.errorCode, subtitle: subtitle))));
Navigator.of(context).pop();
},
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
reset();
notifyListeners();
}
return response.statusCode;
} catch (error) {
return -1;
}
}
Future<int> updateServiceReport({
required String host,
required User user,
required ServiceReport report,
required ServiceRequest request,
}) async {
Response response;
Map<String, String> body = report.toMap();
body["uid"] = user.id ?? "";
body["token"] = user.token ?? "";
body["job_id"] = request.id ?? '';
body["report_id"] = request.reportID ?? '';
try {
response = await post(
Uri.parse(host + URLs.updateServiceReport),
body: body,
);
stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
void updateServiceReport(BuildContext context, {required ServiceReport report, required ServiceRequest request}) {
final subtitle = AppLocalization.of(context)?.subtitle;
waitApiRequest(
() async {
await ServiceRequestApiClient().updateServiceReport(report: report, request: request);
reset();
notifyListeners();
}
return response.statusCode;
} catch (error) {
return -1;
}
},
onSuccess: () {
Fluttertoast.showToast(msg: subtitle?.requestCompleteSuccessfully ?? '');
Navigator.of(context).pop();
Navigator.of(context).pop();
/// TODO : this is temporary
stateCode = 200;
},
onError: (error) {
/// TODO : this is temporary
stateCode = error.error?.errorCode;
String errorMessage = HttpStatusManger.getStatusMessage(status: error.error?.errorCode, subtitle: subtitle);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(errorMessage)));
},
);
}
Future<int> updateServiceReportTimer({
required String host,
required User user,
required TimerModel timer,
required ServiceRequest request,
}) async {
Response response;
Map<String, String> body = {};
body["uid"] = user.id ?? "";
body["token"] = user.token ?? "";
body["job_id"] = request.id ?? '';
body["start_time"] = ((timer.startAt?.millisecondsSinceEpoch ?? 0) / 1000).toStringAsFixed(0);
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 ?? '';
Future updateServiceReportTimer({required TimerModel timer, required ServiceRequest request}) async {
try {
response = await post(
Uri.parse(host + URLs.updateServiceReport),
body: body,
);
//stateCode = response.statusCode;
await ServiceRequestApiClient().updateServiceReportTimer(timer: timer, request: request);
if (response.statusCode >= 200 && response.statusCode < 300) {
// reset();
// notifyListeners();
}
return response.statusCode;
} catch (error) {
return -1;
/// TODO : this is temporary
stateCode = 200;
} on APIException catch (error) {
/// TODO : this is temporary
stateCode = error.error?.errorCode;
}
}
Future<ServiceReport> getSingleServiceReport({
required String reportId,
required String host,
required User user,
required Subtitle subtitle,
}) async {
String userData = '';
userData += "&uid=${user.id}";
userData += "&token=${user.token}";
Response response;
try {
response = await get(Uri.parse(
'$host${URLs.getServiceReport}?report_id=$reportId$userData',
));
} catch (error) {
throw (HttpStatusManger.getStatusMessage(status: -1, subtitle: subtitle) ?? '');
}
// If the call to the server was successful, parse the JSON.
if (response.statusCode >= 200 && response.statusCode < 300) {
// If the call to the server was successful, parse the JSON.
return ServiceReport.fromJson(json.decode(utf8.decode(response.bodyBytes)), reportId);
} else {
throw (HttpStatusManger.getStatusMessage(
status: response.statusCode,
subtitle: subtitle,
) ??
'');
}
Future<ServiceReport?> getSingleServiceReport({required String reportId}) async {
return await ServiceRequestApiClient().getSingleServiceReport(reportId: reportId);
}
}

@ -1,17 +1,11 @@
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart';
import '../../../api/user_api_client.dart';
import '../../../controllers/localization/localization.dart';
import '../../../controllers/providers/api/service_requests_provider.dart';
import '../../../controllers/providers/settings/setting_provider.dart';
import '../../../controllers/providers/user_provider.dart';
import '../../../controllers/validator/validator.dart';
import '../../../models/issue.dart';
import '../../../models/service_request/service_request.dart';
import '../../../models/subtitle.dart';
import '../../../models/user.dart';
import '../../app_style/colors.dart';
import '../../app_style/sizing.dart';
import '../../widgets/app_text_form_field.dart';
@ -25,27 +19,24 @@ class ReportIssuesPage extends StatefulWidget {
final ServiceRequest? serviceRequest;
const ReportIssuesPage({Key? key, this.serviceRequest}) : super(key: key);
@override
_ReportIssuesPageState createState() => _ReportIssuesPageState();
ReportIssuesPageState createState() => ReportIssuesPageState();
}
class _ReportIssuesPageState extends State<ReportIssuesPage> {
List<String> _issues = [];
Issue _issue = Issue(reports: []);
class ReportIssuesPageState extends State<ReportIssuesPage> {
final List<String> _issues = [];
final Issue _issue = Issue(reports: []);
late double _height;
bool _isLoading = false;
late ServiceRequestsProvider _serviceRequestsProvider;
late UserProvider _userProvider;
late SettingProvider _settingProvider;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
Subtitle _subtitle = AppLocalization.of(context)!.subtitle!;
final subtitle = AppLocalization.of(context)?.subtitle;
_serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context);
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context);
_height = MediaQuery.of(context).size.height;
_subtitle.setIssues(_issues);
subtitle?.setIssues(_issues);
return Scaffold(
body: SafeArea(
child: Form(
@ -54,7 +45,7 @@ class _ReportIssuesPageState extends State<ReportIssuesPage> {
onRefresh: () async {},
stateCode: 200,
isFailedLoading: false,
isLoading: _isLoading,
isLoading: _serviceRequestsProvider.loading,
child: Stack(
children: [
SingleChildScrollView(
@ -67,27 +58,21 @@ class _ReportIssuesPageState extends State<ReportIssuesPage> {
vertical: 24 * AppStyle.getScaleFactor(context),
),
child: Text(
_subtitle.reportIssue,
style: Theme.of(context).textTheme.headline5?.copyWith(color: AColors.cyan, fontWeight: FontWeight.bold),
subtitle?.reportIssue ?? '',
style: Theme.of(context).textTheme.headlineSmall?.copyWith(color: AColors.cyan, fontWeight: FontWeight.bold),
),
),
),
Image(
height: _height / 8,
image: AssetImage("assets/images/logo.png"),
),
Image(height: _height / 8, image: const AssetImage("assets/images/logo.png")),
Container(
padding: EdgeInsets.symmetric(
horizontal: 16,
vertical: 16,
),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
decoration: BoxDecoration(
color: AColors.grey,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(AppStyle.getBorderRadius(context)),
topRight: Radius.circular(AppStyle.getBorderRadius(context)),
),
boxShadow: [
boxShadow: const [
BoxShadow(
color: AColors.grey,
offset: Offset(0, -1),
@ -97,19 +82,17 @@ class _ReportIssuesPageState extends State<ReportIssuesPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ATextFormField(
initialValue: _issue?.title,
hintText: _subtitle.title,
initialValue: _issue.title,
hintText: subtitle?.title,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headline6,
validator: (value) => Validator.hasValue(value!) ? '' : _subtitle.titleValidateMessage,
style: Theme.of(context).textTheme.titleLarge,
validator: (value) => Validator.hasValue(value) ? null : subtitle?.titleValidateMessage,
textInputType: TextInputType.name,
onSaved: (value) {
_issue.title = value;
},
),
SizedBox(
height: 8,
),
const SizedBox(height: 8),
Column(
children: List.generate(
_issues.length,
@ -128,13 +111,13 @@ class _ReportIssuesPageState extends State<ReportIssuesPage> {
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"${_subtitle.shareAntherIssue} :",
style: Theme.of(context).textTheme.headline6,
"${subtitle?.shareAntherIssue} :",
style: Theme.of(context).textTheme.titleLarge,
),
),
ATextFormField(
hintText: _subtitle.description,
style: Theme.of(context).textTheme.subtitle1,
hintText: subtitle?.description,
style: Theme.of(context).textTheme.titleMedium,
textInputType: TextInputType.multiline,
onSaved: (value) {
_issue.description = value;
@ -143,28 +126,13 @@ class _ReportIssuesPageState extends State<ReportIssuesPage> {
Padding(
padding: const EdgeInsets.all(8.0),
child: AButton(
text: _subtitle.submit,
text: subtitle?.submit ?? '',
onPressed: () async {
if (!(_formKey.currentState?.validate() ?? false)) return;
_formKey.currentState?.save();
_issue.serviceRequestId = widget.serviceRequest?.id;
_isLoading = true;
setState(() {});
int status = await _serviceRequestsProvider.createIssueReport(
user: UserApiClient().user ?? User(),
host: _settingProvider.host ?? "",
issue: _issue,
);
_isLoading = false;
setState(() {});
if (status >= 200 && status < 300) {
Fluttertoast.showToast(
msg: _subtitle.requestCompleteSuccessfully,
);
Navigator.of(context).pop();
if (_formKey.currentState?.validate() ?? false) {
_issue.serviceRequestId = widget.serviceRequest?.id;
_formKey.currentState?.save();
_serviceRequestsProvider.createIssueReport(context, issue: _issue);
}
_isLoading = false;
setState(() {});
},
),
),
@ -174,7 +142,7 @@ class _ReportIssuesPageState extends State<ReportIssuesPage> {
],
),
),
ABackButton(),
const ABackButton(),
],
),
),

@ -1,13 +1,10 @@
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/service_requests_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../controllers/providers/user_provider.dart';
import '../../../../models/service_request/service_request.dart';
import '../../../../models/subtitle.dart';
import '../../../widgets/loaders/app_loading.dart';
import '../../../widgets/loaders/failed_loading.dart';
import 'request_details.dart';
@ -29,10 +26,9 @@ class _FutureRequestServiceDetailsState extends State<FutureRequestServiceDetail
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context);
String? requestId = ModalRoute.of(context)?.settings.arguments as String?;
Subtitle _subtitle = AppLocalization.of(context)!.subtitle!;
return Scaffold(
body: FutureBuilder<ServiceRequest>(
future: ServiceRequestsProvider().getSingleServiceRequest(requestId: requestId ?? '', user: UserApiClient().user!, host: _settingProvider.host ?? "", subtitle: _subtitle),
future: ServiceRequestsProvider().getSingleServiceRequest(requestId: requestId),
builder: (BuildContext context, AsyncSnapshot<ServiceRequest> snapshot) {
if (snapshot.hasError) {
return FailedLoading(

@ -2,15 +2,11 @@ import 'dart:convert';
import 'dart:io';
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/service_requests_provider.dart';
import '../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import '../../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../../controllers/validator/validator.dart';
import '../../../../../models/device/device.dart';
import '../../../../../models/lookup.dart';
@ -48,12 +44,10 @@ class CreateServiceReport extends StatefulWidget {
}
class CreateServiceReportState extends State<CreateServiceReport> with TickerProviderStateMixin {
SettingProvider? _settingProvider;
ServiceRequestsProvider? _serviceRequestsProvider;
bool _validate = false;
ServiceReport? _serviceReport;
bool _isLoading = false;
Subtitle? _subtitle;
File? _image;
@ -84,14 +78,13 @@ class CreateServiceReportState extends State<CreateServiceReport> with TickerPro
@override
Widget build(BuildContext context) {
_settingProvider = Provider.of<SettingProvider>(context);
_serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context);
_subtitle = AppLocalization.of(context)?.subtitle;
return Scaffold(
key: _scaffoldKey,
body: SafeArea(
child: LoadingManager(
isLoading: _isLoading,
isLoading: _serviceRequestsProvider?.loading,
isFailedLoading: false,
stateCode: 200,
onRefresh: () async {},
@ -110,15 +103,15 @@ class CreateServiceReportState extends State<CreateServiceReport> with TickerPro
padding: const EdgeInsets.all(8.0),
child: Text(
_subtitle?.newServiceReport ?? "",
style: Theme.of(context).textTheme.headline5?.copyWith(color: AColors.cyan, fontSize: 28, fontWeight: FontWeight.bold),
style: Theme.of(context).textTheme.headlineSmall?.copyWith(color: AColors.cyan, fontSize: 28, fontWeight: FontWeight.bold),
),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [
const BoxShadow(
decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: const [
BoxShadow(
color: AColors.grey,
offset: Offset(0, -1),
)
@ -144,7 +137,7 @@ class CreateServiceReportState extends State<CreateServiceReport> with TickerPro
),
Text(
"${_subtitle?.customer}: ${widget.request?.hospitalName}",
style: Theme.of(context).textTheme.subtitle1?.copyWith(
style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
fontSize: 12,
),
@ -343,7 +336,7 @@ class CreateServiceReportState extends State<CreateServiceReport> with TickerPro
ATextFormField(
initialValue: _serviceReport?.invoiceNumber ?? "",
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle1,
style: Theme.of(context).textTheme.titleMedium,
validator: (value) => Validator.hasValue(value!) ? '' : _subtitle?.requiredWord ?? "",
textInputType: TextInputType.number,
onSaved: (value) {
@ -367,7 +360,7 @@ class CreateServiceReportState extends State<CreateServiceReport> with TickerPro
ATextFormField(
initialValue: _serviceReport?.invoiceCode ?? "",
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle1,
style: Theme.of(context).textTheme.titleMedium,
validator: (value) => Validator.hasValue(value!) ? '' : _subtitle?.requiredWord ?? "",
textInputType: TextInputType.text,
onSaved: (value) {
@ -389,10 +382,7 @@ class CreateServiceReportState extends State<CreateServiceReport> with TickerPro
Expanded(
child: SizedBox(
height: 32 * AppStyle.getScaleFactor(context),
child: SpeechToTextButton(
controller: _faultController,
mini: true,
),
child: SpeechToTextButton(controller: _faultController, mini: true),
),
),
],
@ -404,7 +394,7 @@ class CreateServiceReportState extends State<CreateServiceReport> with TickerPro
initialValue: _serviceReport?.faultDescription ?? "",
textAlign: TextAlign.center,
controller: _faultController,
style: Theme.of(context).textTheme.subtitle1,
style: Theme.of(context).textTheme.titleMedium,
validator: (value) => Validator.hasValue(value!) ? '' : _subtitle?.requiredWord ?? "",
textInputType: TextInputType.multiline,
onSaved: (value) {
@ -435,7 +425,7 @@ class CreateServiceReportState extends State<CreateServiceReport> with TickerPro
initialValue: _serviceReport?.workPreformed ?? "",
textAlign: TextAlign.center,
controller: _workPreformedController,
style: Theme.of(context).textTheme.subtitle1,
style: Theme.of(context).textTheme.titleMedium,
validator: (value) => Validator.hasValue(value!) ? '' : _subtitle?.requiredWord ?? "",
textInputType: TextInputType.multiline,
onSaved: (value) {
@ -542,7 +532,7 @@ class CreateServiceReportState extends State<CreateServiceReport> with TickerPro
initialValue: _serviceReport?.travelingHours,
textAlign: TextAlign.center,
hintText: "i.e 3, 3.5, 4",
style: Theme.of(context).textTheme.subtitle1,
style: Theme.of(context).textTheme.titleMedium,
// validator: (value) =>
// Validator.isNumeric(value)
// ? null : _subtitle.requiredWord,
@ -596,7 +586,7 @@ class CreateServiceReportState extends State<CreateServiceReport> with TickerPro
ATextFormField(
initialValue: _serviceReport?.jobSheetNumber,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle1,
style: Theme.of(context).textTheme.titleMedium,
textInputType: TextInputType.name,
onSaved: (value) {
_serviceReport?.jobSheetNumber = value;
@ -649,9 +639,9 @@ class CreateServiceReportState extends State<CreateServiceReport> with TickerPro
),
Column(
children: List.generate(_serviceReport!.parts!.length, (index) {
Part _part = _serviceReport!.parts![index];
Part part = _serviceReport!.parts![index];
return PartItem(
part: _part,
part: part,
onDelete: (part) {
_serviceReport!.parts!.remove(part);
setState(() {});
@ -672,31 +662,9 @@ class CreateServiceReportState extends State<CreateServiceReport> with TickerPro
text: _subtitle?.submit ?? "",
onPressed: () async {
_validate = true;
if (!(_formKey.currentState?.validate() ?? false)) {
setState(() {});
return;
}
if (!(_serviceReport?.validate() ?? false)) return;
_formKey.currentState?.save();
_isLoading = true;
setState(() {});
int? status =
await _serviceRequestsProvider?.createServiceReport(user: UserApiClient().user!, host: _settingProvider?.host ?? "", report: _serviceReport!, request: widget.request!);
_isLoading = false;
setState(() {});
if (status != null && status >= 200 && status < 300) {
Fluttertoast.showToast(
msg: _subtitle?.requestCompleteSuccessfully ?? "",
);
Navigator.of(context).pop();
Navigator.of(context).pop();
} else {
String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(errorMessage),
));
if (_formKey.currentState?.validate() ?? false) {
_formKey.currentState?.save();
_serviceRequestsProvider?.createServiceReport(context, report: _serviceReport, request: widget.request);
}
},
),

@ -2,16 +2,11 @@ import 'dart:convert';
import 'dart:io';
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/service_requests_provider.dart';
import '../../../../../controllers/providers/api/status_drop_down/report/service_report_last_calls_provider.dart';
import '../../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../../controllers/providers/user_provider.dart';
import '../../../../../controllers/validator/validator.dart';
import '../../../../../models/part.dart';
import '../../../../../models/service_report.dart';
@ -38,30 +33,27 @@ import '../../../../widgets/timer/app_timer.dart';
import '../../../../widgets/titles/app_sub_title.dart';
class EditServiceReport extends StatefulWidget {
static final String id = "/edit-service-report";
static const String id = "/edit-service-report";
final ServiceRequest request;
final ServiceReport report;
const EditServiceReport({Key? key, required this.request, required this.report}) : super(key: key);
@override
_EditServiceReportState createState() => _EditServiceReportState();
EditServiceReportState createState() => EditServiceReportState();
}
class _EditServiceReportState extends State<EditServiceReport> with TickerProviderStateMixin {
late UserProvider _userProvider;
late SettingProvider _settingProvider;
class EditServiceReportState extends State<EditServiceReport> with TickerProviderStateMixin {
late ServiceRequestsProvider _serviceRequestsProvider;
bool _validate = false;
late ServiceReport _serviceReport;
bool _isLoading = false;
late Subtitle _subtitle;
late File _image;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
TextEditingController _faultController = TextEditingController();
TextEditingController _workPreformedController = TextEditingController();
final TextEditingController _faultController = TextEditingController();
final TextEditingController _workPreformedController = TextEditingController();
@override
void initState() {
@ -78,15 +70,13 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
@override
Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context);
_serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context);
_subtitle = AppLocalization.of(context)!.subtitle!;
return Scaffold(
key: _scaffoldKey,
body: SafeArea(
child: LoadingManager(
isLoading: _isLoading,
isLoading: _serviceRequestsProvider.loading,
isFailedLoading: false,
stateCode: 200,
onRefresh: () async {},
@ -105,14 +95,14 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
padding: const EdgeInsets.all(8.0),
child: Text(
_subtitle.editServiceReport,
style: Theme.of(context).textTheme.headline5?.copyWith(color: AColors.cyan, fontSize: 28, fontWeight: FontWeight.bold),
style: Theme.of(context).textTheme.headlineSmall?.copyWith(color: AColors.cyan, fontSize: 28, fontWeight: FontWeight.bold),
),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [
decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: const [
BoxShadow(
color: AColors.grey,
offset: Offset(0, -1),
@ -121,28 +111,15 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 8,
),
const SizedBox(height: 8),
Wrap(
spacing: 10,
children: [
ASubTitle(
"${_subtitle.callId}: ${widget.request.requestCode}",
font: 14,
),
widget.request.deviceSerialNumber == null
? const SizedBox()
: ASubTitle(
"${_subtitle.deviceSN}: ${widget.request.deviceSerialNumber}",
font: 14,
),
ASubTitle("${_subtitle.callId}: ${widget.request.requestCode}", font: 14),
widget.request.deviceSerialNumber == null ? const SizedBox() : ASubTitle("${_subtitle.deviceSN}: ${widget.request.deviceSerialNumber}", font: 14),
Text(
"${_subtitle.customer}: ${widget.request.hospitalName}",
style: Theme.of(context).textTheme.subtitle1?.copyWith(
fontWeight: FontWeight.bold,
fontSize: 12,
),
style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold, fontSize: 12),
textScaleFactor: AppStyle.getScaleFactor(context),
)
],
@ -158,15 +135,8 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ASubTitle(_subtitle.reportType),
_validate && _serviceReport.type == null
? ASubTitle(
_subtitle.requiredWord,
color: Colors.red,
)
: const SizedBox.shrink(),
const SizedBox(
height: 4,
),
_validate && _serviceReport.type == null ? ASubTitle(_subtitle.requiredWord, color: Colors.red) : const SizedBox.shrink(),
const SizedBox(height: 4),
ServiceReportTypeMenu(
initialValue: _serviceReport.type,
onSelect: (status) {
@ -176,21 +146,14 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
],
),
),
const SizedBox(
width: 8,
),
const SizedBox(width: 8),
// visit date
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ASubTitle(_subtitle.visitDate),
_validate && _serviceReport.visitDate == null
? ASubTitle(
_subtitle.requiredWord,
color: Colors.red,
)
: const SizedBox.shrink(),
_validate && _serviceReport.visitDate == null ? ASubTitle(_subtitle.requiredWord, color: Colors.red) : const SizedBox.shrink(),
Row(
children: [
Expanded(
@ -211,9 +174,7 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
),
],
),
const SizedBox(
height: 8,
),
const SizedBox(height: 8),
// device sn
Visibility(
visible: true, //widget.report.device == null,
@ -221,12 +182,7 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ASubTitle(_subtitle.deviceSN),
_validate && _serviceReport.device?.id == null
? ASubTitle(
_subtitle.requiredWord,
color: Colors.red,
)
: const SizedBox.shrink(),
_validate && _serviceReport.device?.id == null ? ASubTitle(_subtitle.requiredWord, color: Colors.red) : const SizedBox.shrink(),
AutoCompleteDeviceField(
hospitalId: widget.request.hospitalId,
initialValue: _serviceReport.device!,
@ -234,34 +190,21 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
_serviceReport.device?.id = id;
},
),
const SizedBox(
height: 8,
),
const SizedBox(height: 8),
],
),
),
const SizedBox(
height: 8,
),
const SizedBox(height: 8),
ASubTitle(_subtitle.serviceType),
_validate && _serviceReport.serviceType == null
? ASubTitle(
_subtitle.requiredWord,
color: Colors.red,
)
: const SizedBox.shrink(),
const SizedBox(
height: 4,
),
_validate && _serviceReport.serviceType == null ? ASubTitle(_subtitle.requiredWord, color: Colors.red) : const SizedBox.shrink(),
const SizedBox(height: 4),
ServiceStatusMenu(
initialValue: _serviceReport.serviceType,
onSelect: (status) {
_serviceReport.serviceType = status;
},
),
const SizedBox(
height: 8,
),
const SizedBox(height: 8),
// Report status and Service Type
Row(
children: [
@ -271,15 +214,8 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ASubTitle(_subtitle.reportStatus),
_validate && _serviceReport.status == null
? ASubTitle(
_subtitle.requiredWord,
color: Colors.red,
)
: const SizedBox.shrink(),
const SizedBox(
height: 4,
),
_validate && _serviceReport.status == null ? ASubTitle(_subtitle.requiredWord, color: Colors.red) : const SizedBox.shrink(),
const SizedBox(height: 4),
ServiceReportStatusMenu(
report: _serviceReport,
onSelect: (status) {
@ -289,9 +225,7 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
],
),
),
const SizedBox(
width: 8,
),
const SizedBox(width: 8),
Provider.of<ServiceReportLastCallsProvider>(context).isLoading == null
? const SizedBox.shrink()
:
@ -301,15 +235,8 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ASubTitle(_subtitle.callLastSituation),
_validate && _serviceReport.callLastSituation == null
? ASubTitle(
_subtitle.requiredWord,
color: Colors.red,
)
: const SizedBox.shrink(),
const SizedBox(
height: 4,
),
_validate && _serviceReport.callLastSituation == null ? ASubTitle(_subtitle.requiredWord, color: Colors.red) : const SizedBox.shrink(),
const SizedBox(height: 4),
ServiceReportLastCallsMenu(
report: _serviceReport,
onSelect: (status) {
@ -326,9 +253,7 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
),
],
),
const SizedBox(
height: 8,
),
const SizedBox(height: 8),
// invoice number & code
_serviceReport.callLastSituation?.id != 12
? const SizedBox.shrink()
@ -339,13 +264,11 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ASubTitle(_subtitle.invoiceNumber),
const SizedBox(
height: 8,
),
const SizedBox(height: 8),
ATextFormField(
initialValue: _serviceReport?.invoiceNumber,
initialValue: _serviceReport.invoiceNumber,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle1,
style: Theme.of(context).textTheme.titleMedium,
validator: (value) => Validator.hasValue(value!) ? '' : _subtitle.requiredWord,
textInputType: TextInputType.number,
onSaved: (value) {
@ -355,21 +278,17 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
],
),
),
const SizedBox(
width: 8,
),
const SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ASubTitle(_subtitle.invoiceCode),
const SizedBox(
height: 4,
),
const SizedBox(height: 4),
ATextFormField(
initialValue: _serviceReport?.invoiceCode,
initialValue: _serviceReport.invoiceCode,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle1,
style: Theme.of(context).textTheme.titleMedium,
validator: (value) => Validator.hasValue(value!) ? '' : _subtitle.requiredWord,
textInputType: TextInputType.text,
onSaved: (value) {
@ -382,19 +301,14 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
],
),
const SizedBox(
height: 8,
),
const SizedBox(height: 8),
Row(
children: [
ASubTitle(_subtitle.faultDescription),
Expanded(
child: SizedBox(
height: 32 * AppStyle.getScaleFactor(context),
child: SpeechToTextButton(
controller: _faultController,
mini: true,
),
child: SpeechToTextButton(controller: _faultController, mini: true),
),
),
],
@ -403,29 +317,24 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
height: 4,
),
ATextFormField(
initialValue: _serviceReport?.faultDescription,
initialValue: _serviceReport.faultDescription,
textAlign: TextAlign.center,
controller: _faultController,
style: Theme.of(context).textTheme.subtitle1,
style: Theme.of(context).textTheme.titleMedium,
validator: (value) => Validator.hasValue(value!) ? '' : _subtitle.requiredWord,
textInputType: TextInputType.multiline,
onSaved: (value) {
_serviceReport.faultDescription = value;
},
),
const SizedBox(
height: 8,
),
const SizedBox(height: 8),
Row(
children: [
ASubTitle(_subtitle.workPreformed),
Expanded(
child: SizedBox(
height: 32 * AppStyle.getScaleFactor(context),
child: SpeechToTextButton(
controller: _workPreformedController,
mini: true,
),
child: SpeechToTextButton(controller: _workPreformedController, mini: true),
),
),
],
@ -434,10 +343,10 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
height: 4,
),
ATextFormField(
initialValue: _serviceReport?.workPreformed,
initialValue: _serviceReport.workPreformed,
textAlign: TextAlign.center,
controller: _workPreformedController,
style: Theme.of(context).textTheme.subtitle1,
style: Theme.of(context).textTheme.titleMedium,
validator: (value) => Validator.hasValue(value!) ? '' : _subtitle.requiredWord,
textInputType: TextInputType.multiline,
onSaved: (value) {
@ -503,9 +412,7 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ASubTitle(_subtitle.workingHours),
const SizedBox(
height: 8,
),
const SizedBox(height: 8),
AppTimer(
timer: _serviceReport.timer,
onChange: (timer) async {
@ -529,22 +436,18 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
],
),
),
const SizedBox(
width: 8,
),
const SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ASubTitle(_subtitle.travelingHours),
const SizedBox(
height: 4,
),
const SizedBox(height: 4),
ATextFormField(
initialValue: _serviceReport?.travelingHours,
initialValue: _serviceReport.travelingHours,
textAlign: TextAlign.center,
hintText: "i.e 3, 3.5, 4",
style: Theme.of(context).textTheme.subtitle1,
style: Theme.of(context).textTheme.titleMedium,
validator: (value) => Validator.isNumeric(value!) ? '' : _subtitle.requiredWord,
textInputType: TextInputType.number,
onSaved: (value) {
@ -556,9 +459,7 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
),
],
),
const SizedBox(
height: 8,
),
const SizedBox(height: 8),
// Operating Hours and Job Sheet Number
Row(
children: [
@ -571,10 +472,10 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
height: 4,
),
ATextFormField(
initialValue: _serviceReport?.operatingHours,
initialValue: _serviceReport.operatingHours,
textAlign: TextAlign.center,
hintText: "i.e 3, 3.5, 4",
style: Theme.of(context).textTheme.subtitle1,
style: Theme.of(context).textTheme.titleMedium,
validator: (value) => Validator.isNumeric(value!) ? '' : _subtitle.requiredWord,
textInputType: TextInputType.number,
onSaved: (value) {
@ -596,9 +497,9 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
height: 4,
),
ATextFormField(
initialValue: _serviceReport?.jobSheetNumber,
initialValue: _serviceReport.jobSheetNumber,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle1,
style: Theme.of(context).textTheme.titleMedium,
textInputType: TextInputType.name,
onSaved: (value) {
_serviceReport.jobSheetNumber = value;
@ -609,9 +510,7 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
),
],
),
const SizedBox(
height: 8,
),
const SizedBox(height: 8),
// Part Number and Quantity
Row(
children: [
@ -652,9 +551,9 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
),
Column(
children: List.generate(_serviceReport.parts!.length, (index) {
Part _part = _serviceReport.parts![index];
Part part = _serviceReport.parts![index];
return PartItem(
part: _part,
part: part,
onDelete: (part) {
_serviceReport.parts?.remove(part);
setState(() {});
@ -663,9 +562,7 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
}),
),
const SizedBox(
height: 16,
),
const SizedBox(height: 16),
],
),
),
@ -675,34 +572,9 @@ class _EditServiceReportState extends State<EditServiceReport> with TickerProvid
text: _subtitle.update,
onPressed: () async {
_validate = true;
if (!(_formKey.currentState?.validate() ?? false)) {
setState(() {});
return;
}
if (!_serviceReport.validate()) {
setState(() {});
return;
}
_formKey.currentState?.save();
_isLoading = true;
setState(() {});
int status =
await _serviceRequestsProvider.updateServiceReport(user: UserApiClient().user!, host: _settingProvider.host ?? "", report: _serviceReport, request: widget.request);
_isLoading = false;
setState(() {});
if (status >= 200 && status < 300) {
Fluttertoast.showToast(
msg: _subtitle.requestCompleteSuccessfully,
);
Navigator.of(context).pop();
Navigator.of(context).pop();
} else {
String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(errorMessage),
));
if (_formKey.currentState?.validate() ?? false) {
_formKey.currentState?.save();
_serviceRequestsProvider.updateServiceReport(context, report: _serviceReport, request: widget.request);
}
},
),

@ -1,14 +1,8 @@
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/service_requests_provider.dart';
import '../../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../../controllers/providers/user_provider.dart';
import '../../../../../models/service_report.dart';
import '../../../../../models/service_request/service_request.dart';
import '../../../../../models/subtitle.dart';
import '../../../../widgets/loaders/app_loading.dart';
import '../../../../widgets/loaders/failed_loading.dart';
import 'edit_service_report.dart';
@ -19,35 +13,28 @@ class FutureServiceReport extends StatefulWidget {
const FutureServiceReport({Key? key, required this.request}) : super(key: key);
@override
_FutureServiceReportState createState() => _FutureServiceReportState();
FutureServiceReportState createState() => FutureServiceReportState();
}
class _FutureServiceReportState extends State<FutureServiceReport> {
late UserProvider _userProvider;
late SettingProvider _settingProvider;
class FutureServiceReportState extends State<FutureServiceReport> {
@override
Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context);
Subtitle _subtitle = AppLocalization.of(context)!.subtitle!;
return Scaffold(
body: FutureBuilder<ServiceReport>(
future: ServiceRequestsProvider().getSingleServiceReport(reportId: widget.request.reportID ?? "", user: UserApiClient().user!, host: _settingProvider.host ?? "", subtitle: _subtitle),
builder: (BuildContext context, AsyncSnapshot<ServiceReport> snapshot) {
if (snapshot.hasError)
body: FutureBuilder<ServiceReport?>(
future: ServiceRequestsProvider().getSingleServiceReport(reportId: widget.request.reportID ?? ""),
builder: (BuildContext context, snapshot) {
if (snapshot.hasError) {
return FailedLoading(
message: snapshot.error.toString(),
onReload: () {
setState(() {});
},
);
}
if (snapshot.hasData) {
return EditServiceReport(
report: snapshot.data!,
request: widget.request,
);
return EditServiceReport(report: snapshot.data!, request: widget.request);
}
return Center(child: ALoading());
return const Center(child: ALoading());
},
),
);

@ -3,20 +3,15 @@ import 'package:intl/intl.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/service_requests_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../controllers/providers/user_provider.dart';
import '../../../../models/enums/user_types.dart';
import '../../../../models/service_request/service_request.dart';
import '../../../../models/subtitle.dart';
import '../../../app_style/colors.dart';
import '../../../app_style/sizing.dart';
import '../../../widgets/buttons/app_back_button.dart';
import '../../../widgets/buttons/app_button.dart';
import '../../../widgets/buttons/app_icon_button.dart';
import '../../../widgets/dialogs/dialog.dart';
import '../../../widgets/images/images_list.dart';
import '../../../widgets/loaders/image_loader.dart';
import '../../../widgets/requests/info_row.dart';
@ -29,16 +24,15 @@ import 'report/create_service_report.dart';
import 'report/future_service_report.dart';
class RequestDetailsPage extends StatelessWidget {
static final String id = "/call-details";
static const String id = "/call-details";
final ServiceRequest serviceRequest;
const RequestDetailsPage({Key? key, required this.serviceRequest}) : super(key: key);
@override
Widget build(BuildContext context) {
Subtitle _subtitle = AppLocalization.of(context)!.subtitle!;
UserProvider _userProvider = Provider.of<UserProvider>(context);
SettingProvider _settingProvider = Provider.of<SettingProvider>(context);
ServiceRequestsProvider _serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context);
final subtitle = AppLocalization.of(context)?.subtitle;
ServiceRequestsProvider serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context);
return DefaultTabController(
length: 2,
child: Scaffold(
@ -50,12 +44,12 @@ class RequestDetailsPage extends StatelessWidget {
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 4),
child: Row(
children: [
ABackButton(),
const ABackButton(),
Expanded(
child: Center(
child: Text(
_subtitle.details,
style: Theme.of(context).textTheme.headline6?.copyWith(color: AColors.white, fontStyle: FontStyle.italic),
subtitle?.details ?? '',
style: Theme.of(context).textTheme.titleLarge?.copyWith(color: AColors.white, fontStyle: FontStyle.italic),
),
),
),
@ -70,9 +64,7 @@ class RequestDetailsPage extends StatelessWidget {
showModalBottomSheet(
context: context,
builder: (context) {
return ServiceRequestsUpdateDialog(
request: serviceRequest,
);
return ServiceRequestsUpdateDialog(request: serviceRequest);
});
// DateTime picked = await showDatePicker(
// context: context,
@ -109,173 +101,98 @@ class RequestDetailsPage extends StatelessWidget {
buttonSize: 42,
backgroundColor: AColors.deepOrange,
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => ReportIssuesPage(
serviceRequest: serviceRequest,
)));
Navigator.of(context).push(MaterialPageRoute(builder: (_) => ReportIssuesPage(serviceRequest: serviceRequest)));
},
),
),
SizedBox(
width: 16,
)
const SizedBox(width: 16)
],
),
),
(serviceRequest.devicePhotos?.isEmpty ?? false)
? SizedBox.shrink()
? const SizedBox.shrink()
: Column(
children: [
SizedBox(
height: 8,
),
const SizedBox(height: 8),
MaterialButton(
padding: EdgeInsets.zero,
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => Scaffold(
body: InteractiveViewer(
child: Center(
child: ImageLoader(
url: serviceRequest.devicePhotos?.first,
boxFit: BoxFit.contain,
),
),
),
)));
body: InteractiveViewer(
child: Center(child: ImageLoader(url: serviceRequest.devicePhotos?.first, boxFit: BoxFit.contain)),
),
),
),
);
},
child: SizedBox(
height: 140 * AppStyle.getScaleFactor(context),
width: MediaQuery.of(context).size.width,
child: ImageLoader(
url: serviceRequest.devicePhotos?.first,
boxFit: BoxFit.cover,
),
child: ImageLoader(url: serviceRequest.devicePhotos?.first, boxFit: BoxFit.cover),
),
),
SizedBox(
height: 8,
),
const SizedBox(height: 8),
SizedBox(
height: 60 * AppStyle.getScaleFactor(context),
child: ImagesList(
images: serviceRequest.devicePhotos!,
),
child: ImagesList(images: serviceRequest.devicePhotos!),
),
],
),
TabBar(labelColor: AColors.primaryColor, tabs: [
Tab(
text: _subtitle.general,
),
Tab(
text: _subtitle.serviceRequestInformation,
),
]),
SizedBox(
height: 8,
TabBar(
labelColor: AColors.primaryColor,
tabs: [
Tab(text: subtitle?.general),
Tab(text: subtitle?.serviceRequestInformation),
],
),
const SizedBox(height: 8),
Expanded(
child: TabBarView(
children: [
ListView(
padding: EdgeInsets.symmetric(horizontal: 16),
padding: const EdgeInsets.symmetric(horizontal: 16),
children: [
RequestInfoRow(
title: _subtitle.code,
info: serviceRequest.requestCode,
),
RequestInfoRow(
title: "Asset Number",
info: serviceRequest.deviceNumber,
),
RequestInfoRow(
title: _subtitle.deviceSN,
info: serviceRequest.deviceSerialNumber,
),
RequestInfoRow(
title: _subtitle.deviceModel,
info: serviceRequest.deviceModel,
),
RequestInfoRow(
title: _subtitle.engineerName,
info: serviceRequest.engineerName,
),
RequestInfoRow(
title: _subtitle.engineerPhone,
info: serviceRequest.engineerMobile,
),
RequestInfoRow(
title: _subtitle.date,
info: serviceRequest.date,
),
RequestInfoRow(title: subtitle?.code, info: serviceRequest.requestCode),
RequestInfoRow(title: "Asset Number", info: serviceRequest.deviceNumber),
RequestInfoRow(title: subtitle?.deviceSN, info: serviceRequest.deviceSerialNumber),
RequestInfoRow(title: subtitle?.deviceModel, info: serviceRequest.deviceModel),
RequestInfoRow(title: subtitle?.engineerName, info: serviceRequest.engineerName),
RequestInfoRow(title: subtitle?.engineerPhone, info: serviceRequest.engineerMobile),
RequestInfoRow(title: subtitle?.date, info: serviceRequest.date),
serviceRequest.nextVisitDate == null
? SizedBox.shrink()
: RequestInfoRow(
title: _subtitle.nextVisitDate,
info: DateFormat('EE dd/MM/yyyy').format(serviceRequest.nextVisitDate!),
),
? const SizedBox.shrink()
: RequestInfoRow(title: subtitle?.nextVisitDate, info: DateFormat('EE dd/MM/yyyy').format(serviceRequest.nextVisitDate!)),
Row(
children: [
Expanded(
child: Text(
"${_subtitle.status} : ",
style: Theme.of(context).textTheme.subtitle1,
"${subtitle?.status} : ",
style: Theme.of(context).textTheme.titleMedium,
textScaleFactor: AppStyle.getScaleFactor(context),
),
),
StatusLabel(label: serviceRequest.statusLabel, color: AColors.getRequestStatusColor(serviceRequest.statusValue!)),
],
),
Divider(
color: Theme.of(context).primaryColor,
),
RequestInfoRow(
title: _subtitle.hospital,
info: serviceRequest.hospitalName,
),
RequestInfoRow(
title: _subtitle.unite,
info: serviceRequest.departmentName,
),
Divider(color: Theme.of(context).primaryColor),
RequestInfoRow(title: subtitle?.hospital, info: serviceRequest.hospitalName),
RequestInfoRow(title: subtitle?.unite, info: serviceRequest.departmentName),
// RequestInfoRow(
// title: _subtitle.deviceArName,
// content: serviceRequest.deviceArName,
// ),
RequestInfoRow(
title: _subtitle.deviceEnName,
content: serviceRequest.deviceEnName,
),
RequestInfoRow(
title: _subtitle.maintenanceIssue,
content: serviceRequest.maintenanceIssue,
),
if (serviceRequest.audio?.isNotEmpty == true)
ASoundPlayer(
audio: serviceRequest.audio,
),
RequestInfoRow(title: subtitle?.deviceEnName, content: serviceRequest.deviceEnName),
RequestInfoRow(title: subtitle?.maintenanceIssue, content: serviceRequest.maintenanceIssue),
if (serviceRequest.audio?.isNotEmpty == true) ASoundPlayer(audio: serviceRequest.audio),
Center(
child: Padding(
padding: EdgeInsets.all(32),
padding: const EdgeInsets.all(32),
child: AButton(
text: _subtitle.duplicateRequest,
text: subtitle?.duplicateRequest ?? '',
onPressed: () async {
bool result = await showDialog(
context: context,
builder: (_) => AAlertDialog(
title: _subtitle.duplicateAlert,
content: _subtitle.duplicateAlertMessage,
));
if (result == true) {
showDialog(
context: context,
builder: (context) {
return Center(child: CircularProgressIndicator());
});
int status = await _serviceRequestsProvider.createDuplicatedReport(host: _settingProvider.host ?? "", user: UserApiClient().user!, request: serviceRequest);
Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(HttpStatusManger.getStatusMessage(status: status, subtitle: _subtitle))));
}
serviceRequestsProvider.createDuplicatedReport(context, request: serviceRequest);
},
),
),
@ -284,62 +201,42 @@ class RequestDetailsPage extends StatelessWidget {
),
serviceRequest.viewReport ?? false
? ListView(
padding: EdgeInsets.symmetric(horizontal: 16),
padding: const EdgeInsets.symmetric(horizontal: 16),
children: [
RequestInfoRow(
title: _subtitle.faultDescription,
content: serviceRequest.faultDescription,
),
RequestInfoRow(
title: _subtitle.workPerformed,
content: serviceRequest.workPerformed,
),
RequestInfoRow(
title: _subtitle.visitDate,
info: serviceRequest.visitDate,
),
RequestInfoRow(
title: _subtitle.jobSheetNumber,
info: serviceRequest.jobSheetNumber,
),
RequestInfoRow(title: subtitle?.faultDescription, content: serviceRequest.faultDescription),
RequestInfoRow(title: subtitle?.workPerformed, content: serviceRequest.workPerformed),
RequestInfoRow(title: subtitle?.visitDate, info: serviceRequest.visitDate),
RequestInfoRow(title: subtitle?.jobSheetNumber, info: serviceRequest.jobSheetNumber),
UserApiClient().user?.type == UsersTypes.engineer
? Padding(
padding: EdgeInsets.all(32),
padding: const EdgeInsets.all(32),
child: AButton(
text: _subtitle.editServiceReport,
text: subtitle?.editServiceReport ?? '',
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => FutureServiceReport(
request: serviceRequest,
)),
MaterialPageRoute(builder: (_) => FutureServiceReport(request: serviceRequest)),
);
},
),
)
: SizedBox.shrink(),
: const SizedBox.shrink(),
],
)
: UserApiClient().user?.type == UsersTypes.engineer
? Center(
child: Padding(
padding: EdgeInsets.all(32),
padding: const EdgeInsets.all(32),
child: AButton(
text: "Create Report",
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => CreateServiceReport(
request: serviceRequest,
)),
MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest)),
);
},
),
),
)
: Center(
child: ASubTitle(_subtitle.noDateFound),
),
: Center(child: ASubTitle(subtitle?.noDateFound ?? '')),
],
),
),

@ -2,10 +2,8 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/api/service_request_api_client.dart';
import '../../../../api/user_api_client.dart';
import '../../../../controllers/localization/localization.dart';
import '../../../../controllers/providers/api/service_requests_provider.dart';
import '../../../../controllers/providers/settings/setting_provider.dart';
import '../../../../models/service_request/service_request_search.dart';
import '../../../../models/subtitle.dart';
import '../../../app_style/colors.dart';
@ -26,14 +24,12 @@ class ServiceRequestsPage extends StatefulWidget {
class ServiceRequestsPageState extends State<ServiceRequestsPage> with TickerProviderStateMixin {
late ServiceRequestsProvider _serviceRequestsProvider;
late SettingProvider _settingProvider;
final bool _expandedSearch = false;
bool _firstTime = true;
@override
Widget build(BuildContext context) {
_serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context);
Subtitle? subtitle = AppLocalization.of(context)?.subtitle;
if (_firstTime) {
_serviceRequestsProvider.reset();
@ -43,15 +39,11 @@ class ServiceRequestsPageState extends State<ServiceRequestsPage> with TickerPro
return Scaffold(
body: SafeArea(
child: LoadingManager(
isLoading: _serviceRequestsProvider.isLoading,
isLoading: _serviceRequestsProvider.loading,
stateCode: _serviceRequestsProvider.stateCode,
onRefresh: () async {
_serviceRequestsProvider.reset();
await _serviceRequestsProvider.getRequests(
user: UserApiClient().user!,
host: _settingProvider.host ?? "",
hospitalId: UserApiClient().user!.hospital!.id,
);
_serviceRequestsProvider.getRequests();
},
child: Stack(
children: [
@ -87,9 +79,7 @@ class ServiceRequestsPageState extends State<ServiceRequestsPage> with TickerPro
context: context,
isScrollControlled: true,
builder: (context) {
return ServiceRequestsSearchDialog(
initialSearchValue: _serviceRequestsProvider.search!,
);
return ServiceRequestsSearchDialog(initialSearchValue: _serviceRequestsProvider.search!);
},
);
if (temp != null) {
@ -109,11 +99,7 @@ class ServiceRequestsPageState extends State<ServiceRequestsPage> with TickerPro
child: ServiceRequestsList(
nextPage: _serviceRequestsProvider.nextPage!,
onLazyLoad: () async {
await _serviceRequestsProvider.getRequests(
user: UserApiClient().user,
host: _settingProvider.host ?? "",
hospitalId: UserApiClient().user?.hospital?.id,
);
_serviceRequestsProvider.getRequests();
},
requests: ServiceRequestApiClient().serviceRequests,
),

@ -1,14 +1,9 @@
import 'package:flutter/cupertino.dart';
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/service_requests_provider.dart';
import '../../../controllers/providers/settings/setting_provider.dart';
import '../../../controllers/providers/user_provider.dart';
import '../../../models/lookup.dart';
import '../../../models/service_request/service_request.dart';
import '../../../models/subtitle.dart';
@ -33,45 +28,10 @@ class _ServiceRequestsUpdateDialogState extends State<ServiceRequestsUpdateDialo
DateTime? _dateTime;
Lookup? _employee;
Subtitle? _subtitle;
UserProvider? _userProvider;
SettingProvider? _settingProvider;
ServiceRequestsProvider? _serviceRequestsProvider;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
_update() async {
if (_dateTime == null && _employee == null) {
Fluttertoast.showToast(msg: _subtitle?.noDateFound ?? '');
return;
}
showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return CupertinoAlertDialog(
title: Text(_subtitle?.updatingDots ?? ''),
content: const Center(child: CircularProgressIndicator()),
);
},
);
int? status = await _serviceRequestsProvider?.updateDate(
user: UserApiClient().user,
host: _settingProvider?.host,
request: widget.request,
newDate: _dateTime?.toString().split(" ").first,
employee: _employee,
);
if (status == 200) Navigator.of(context).pop();
Navigator.of(context).pop();
Fluttertoast.showToast(
msg: HttpStatusManger.getStatusMessage(
status: status,
subtitle: _subtitle,
) ??
'',
);
}
@override
void initState() {
super.initState();
@ -80,8 +40,6 @@ class _ServiceRequestsUpdateDialogState extends State<ServiceRequestsUpdateDialo
@override
Widget build(BuildContext context) {
_subtitle = AppLocalization.of(context)?.subtitle;
_userProvider = Provider.of<UserProvider>(context, listen: false);
_settingProvider = Provider.of<SettingProvider>(context, listen: false);
_serviceRequestsProvider = Provider.of<ServiceRequestsProvider>(context, listen: false);
return Column(
mainAxisSize: MainAxisSize.min,
@ -105,7 +63,13 @@ class _ServiceRequestsUpdateDialogState extends State<ServiceRequestsUpdateDialo
),
ASmallButton(
text: _subtitle?.update,
onPressed: _update,
onPressed: () {
if (_dateTime == null && _employee == null) {
Fluttertoast.showToast(msg: _subtitle?.noDateFound ?? '');
return;
}
_serviceRequestsProvider?.updateDate(context, request: widget.request, newDate: _dateTime?.toString().split(" ").first, employee: _employee);
},
)
],
),
@ -115,7 +79,7 @@ class _ServiceRequestsUpdateDialogState extends State<ServiceRequestsUpdateDialo
Expanded(
child: Text(
_subtitle?.date ?? '',
style: Theme.of(context).textTheme.subtitle1,
style: Theme.of(context).textTheme.titleMedium,
textScaleFactor: AppStyle.getScaleFactor(context),
),
),

@ -69,9 +69,10 @@ class ServiceRequestsSearchDialogState extends State<ServiceRequestsSearchDialog
ASmallButton(
text: subtitle?.search,
onPressed: () {
if (!(_formKey.currentState?.validate() ?? true)) return;
_formKey.currentState?.save();
Navigator.of(context).pop(_search);
if (_formKey.currentState?.validate() ?? false) {
_formKey.currentState?.save();
Navigator.of(context).pop(_search);
}
},
)
],
@ -83,9 +84,10 @@ class ServiceRequestsSearchDialogState extends State<ServiceRequestsSearchDialog
style: Theme.of(context).textTheme.titleLarge,
textInputAction: TextInputAction.search,
onAction: () {
if (!(_formKey.currentState?.validate() ?? true)) return;
_formKey.currentState?.save();
Navigator.of(context).pop(_search);
if (_formKey.currentState?.validate() ?? false) {
_formKey.currentState?.save();
Navigator.of(context).pop(_search);
}
},
onSaved: (value) {
_search.deviceSerialNumber = value;
@ -113,9 +115,10 @@ class ServiceRequestsSearchDialogState extends State<ServiceRequestsSearchDialog
style: Theme.of(context).textTheme.titleLarge,
textInputAction: TextInputAction.search,
onAction: () {
if (!(_formKey.currentState?.validate() ?? true)) return;
_formKey.currentState?.save();
Navigator.of(context).pop(_search);
if (_formKey.currentState?.validate() ?? false) {
_formKey.currentState?.save();
Navigator.of(context).pop(_search);
}
},
onSaved: (value) {
_search.deviceName = value;
@ -128,9 +131,10 @@ class ServiceRequestsSearchDialogState extends State<ServiceRequestsSearchDialog
style: Theme.of(context).textTheme.titleLarge,
textInputAction: TextInputAction.search,
onAction: () {
if (!(_formKey.currentState?.validate() ?? true)) return;
_formKey.currentState?.save();
Navigator.of(context).pop(_search);
if (_formKey.currentState?.validate() ?? false) {
_formKey.currentState?.save();
Navigator.of(context).pop(_search);
}
},
onSaved: (value) {
_search.model = value;
@ -145,21 +149,24 @@ class ServiceRequestsSearchDialogState extends State<ServiceRequestsSearchDialog
spacing: 10,
runSpacing: 10,
alignment: WrapAlignment.spaceEvenly,
children: List.generate(status.length, (index) {
bool isSelected = _search.statusValue == status[index].id;
return FilterItem(
isSelected: isSelected,
onSelected: () {
if (isSelected) {
_search.statusValue = null;
} else {
_search.statusValue = status[index].id;
}
setState(() {});
},
status: status[index],
);
}),
children: List.generate(
status.length,
(index) {
bool isSelected = _search.statusValue == status[index].id;
return FilterItem(
isSelected: isSelected,
onSelected: () {
if (isSelected) {
_search.statusValue = null;
} else {
_search.statusValue = status[index].id;
}
setState(() {});
},
status: status[index],
);
},
),
),
),
Visibility(

Loading…
Cancel
Save