Merge remote-tracking branch 'origin/main_design2.0' into main_design2.0

# Conflicts:
#	lib/l10n/app_ar.arb
#	lib/l10n/app_en.arb
main_design2.0
nextwo 2 years ago
commit a85d8f4880

@ -232,10 +232,7 @@ class ServiceRequestsProvider extends ChangeNotifier {
}
}
Future<int> updateRequest({
@required User user,
@required ServiceRequest request,
}) async {
Future<int> updateRequest({@required User user, @required ServiceRequest request}) async {
isLoading = true;
notifyListeners();
Map<String, dynamic> serviceRequest = await getServiceRequestById(requestId: request.id) ?? "";
@ -464,42 +461,28 @@ class ServiceRequestsProvider extends ChangeNotifier {
}
}
Future<int> updateServiceReport({
@required ServiceReport report,
String host,
User user,
ServiceRequest request,
}) async {
Future<int> updateServiceReport(BuildContext context, {@required ServiceReport report}) async {
Response response;
//Map<String,dynamic> body = report.toMap(request);
// body["uid"] = user.id;
// body["token"] = user.token;
// body["job_id"] = request.id;
// body["report_id"] = request.reportID;
// try {
report.callRequest = CallRequest(id: report.callRequest.id);
Map<String, dynamic> body = report.toJson();
/// todo [zaid] : don't forget to add [request] data to [body]
// Map<String, dynamic> body = report.toMap(request);
// body["uid"] = user.id;
// body["token"] = user.token;
response = await ApiManager.instance.put(URLs.updateServiceReport, body: body);
// response = await post(
// Uri.parse(
// host+URLs.updateServiceReport),
// body: body,
// );
// stateCode = response.statusCode;
if (response.statusCode >= 200 && response.statusCode < 300) {
reset();
notifyListeners();
try {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
response = await ApiManager.instance.put(URLs.updateServiceReport, body: body);
if (response.statusCode >= 200 && response.statusCode < 300) {
reset();
notifyListeners();
Fluttertoast.showToast(msg: context.translation.successfulRequestMessage);
Navigator.of(context).pop();
} else {
Fluttertoast.showToast(msg: "${context.translation.failedToCompleteRequest}");
}
Navigator.of(context).pop();
return response.statusCode;
} catch (e) {
print(e);
Navigator.of(context).pop();
return -1;
}
return response.statusCode;
// } catch (error) {
// print(error);
// return -1;
// }
}
Future<int> updateWorkOrderDetails({@required SearchWorkOrder workOrder}) async {
@ -563,28 +546,20 @@ class ServiceRequestsProvider extends ChangeNotifier {
}
}
Future<ServiceReport> getSingleServiceReport({
@required int reportId,
@required String host,
@required User user,
@required AppLocalizations subtitle,
}) async {
Future<ServiceReport> getSingleServiceReport(BuildContext context, {@required int reportId}) async {
Response response;
try {
response = await ApiManager.instance.get(
URLs.getServiceReport + "?workOrderId=$reportId",
);
response = await ApiManager.instance.get(URLs.getServiceReport + "?workOrderId=$reportId");
} catch (error) {
throw (HttpStatusManger.getStatusMessage(status: -1, subtitle: subtitle));
throw (context.translation.failedToCompleteRequest);
}
// 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.
/// todo [zaid]: check [reportId] below
return ServiceReport.fromJson(json.decode(response.body)["data"] /*, reportId*/);
return ServiceReport.fromJson(json.decode(response.body)["data"]);
} else {
throw (HttpStatusManger.getStatusMessage(status: response.statusCode, subtitle: subtitle));
throw (("${context.translation.failedToCompleteRequest} ${jsonDecode(response.body)["message"]}"));
}
}

@ -5,4 +5,9 @@ extension StringExtensions on String {
DateTime dateTime = DateTime.tryParse(this);
return "${DateFormat('dd MMM, yyyy').format(dateTime)}\n${DateFormat('hh:mm a').format(dateTime)}";
}
String get toServiceRequestDetailsFormat {
DateTime dateTime = DateTime.tryParse(this);
return "${DateFormat('dd MMM, yyyy').format(dateTime)} ${DateFormat('hh:mm a').format(dateTime)}";
}
}

@ -208,6 +208,8 @@
"pickFromFiles" : "اختر من الملفات",
"requiredFile" : "الملف مطلوب",
"pickFile" : "اختر ملف",
"workOrder" : "طلب عمل",
"workOrders" : "طلبات عمل",
"login" : "تسجيل الدخول",
"enterCredsToLogin" : "أدخل بياناتك الخاصة لتسجيل الدخول",
"forgotPassword" : "نسيت كلمة السر؟",
@ -301,5 +303,6 @@
"assignAssistant" : "تعيين مساعد",
"partNo" : "الجزء رقم",
"engSign" : "توقيع المهندس",
"requesterName" : "اسم الطالب"
"requesterName" : "اسم الطالب",
"updateWorkOrder" : "تعديل طلب العمل"
}

@ -257,7 +257,8 @@
"filter" : "Filter",
"pickAsset" : "Pick Asset",
"firstAction" : "First Action",
"workOrder" : "Work Orders",
"workOrder" : "Work Order",
"workOrders" : "Work Orders",
"viewWorkOrder" : "View All Work Order",
"createWorkOrder" : "Create Work Order",
"viewWorkOrder" : "View All Work Order",
@ -306,5 +307,7 @@
"assignAssistant" : "Assign Assistant",
"partNo" : "Part No.",
"engSign" : "Engineer Signature",
"requesterName" : "Requester Name"
"requesterName" : "Requester Name",
"updateWorkOrder" : "Update Work Order"
}

@ -75,6 +75,8 @@ import 'package:test_sa/views/pages/user/report_issues_page.dart';
import 'package:test_sa/views/pages/user/requests/create_service_request_page.dart';
import 'package:test_sa/views/pages/user/requests/future_request_service_details.dart';
import 'package:test_sa/views/pages/user/requests/requests_page.dart';
import 'package:test_sa/views/pages/user/requests/update_service_request_page.dart';
import 'package:test_sa/views/pages/user/requests/work_order/work_order_details_page.dart';
import 'package:test_sa/views/pages/user/requests/work_order/work_orders_list_page.dart';
import 'package:test_sa/views/pages/user/visits/preventive_maintenance_visits_page.dart';
import 'package:test_sa/views/pages/user/visits/regular_visits_page.dart';
@ -216,6 +218,8 @@ class MyApp extends StatelessWidget {
AssetDetailPage.id: (_) => AssetDetailPage(),
AssetSearchScreen.id: (_) => const AssetSearchScreen(),
AssetFilterScreen.id: (_) => const AssetFilterScreen(),
WorkOrderDetailsPage.id: (_) => const WorkOrderDetailsPage(),
UpdateServiceRequestPage.id: (_) => const UpdateServiceRequestPage(),
},
),
),

@ -1,5 +1,8 @@
import 'dart:typed_data';
import 'package:flutter/cupertino.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/service_request/spare_parts.dart';
import 'package:test_sa/models/service_request/supp_engineer_work_orders.dart';
@ -280,7 +283,7 @@ class ServiceReport {
map['reviewComment'] = reviewComment;
map['comment'] = comment;
if (attachmentsWorkOrder != null) {
map['attachmentsWorkOrder'] = attachmentsWorkOrder.map((v) => v.toJson()).toList();
map['attachmentsWorkOrder'] = attachmentsWorkOrder.map((v) => {"name": v.name}).toList();
}
if (equipmentStatus != null) {
map['equipmentStatus'] = equipmentStatus.toJson();
@ -302,7 +305,19 @@ class ServiceReport {
return map;
}
Future<bool> validate() async {
Future<bool> validate(BuildContext context) async {
if (calllastSituation == null) {
await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.callLastSituation}");
return false;
}
if (sparePartsWorkOrders?.isEmpty ?? true) {
await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.partNo}");
return false;
}
if (reason == null) {
await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.reason}");
return false;
}
return true;
}
}

@ -41,7 +41,7 @@ class SparePartsWorkOrders extends Base {
if (sparePart != null) {
map['sparePart'] = sparePart.toJson();
}
map['qty'] = qty;
map['qty'] = qty ?? 0;
map['returnQty'] = returnQty;
map['installQty'] = installQty;
return map;

@ -171,11 +171,7 @@ class CreateServiceRequestPageState extends State<CreateServiceRequestPage> {
},
),
8.height,
MultiFilesPicker(
label: context.translation.attachImage,
onlyImages: true,
files: _deviceImages,
),
MultiFilesPicker(label: context.translation.attachImage, files: _deviceImages),
((_serviceRequest.devicePhotos?.isNotEmpty ?? false) ? 16 : 8).height,
Align(
alignment: AlignmentDirectional.centerStart,
@ -186,6 +182,10 @@ class CreateServiceRequestPageState extends State<CreateServiceRequestPage> {
controller: _commentController,
labelText: context.translation.comments,
suffixIcon: "warning".toSvgAsset(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, width: 24).paddingOnly(end: 16),
initialValue: _serviceRequest.callComments,
onSaved: (text) {
_serviceRequest.callComments = text;
},
),
8.height,
RecordSound(

@ -15,6 +15,7 @@ import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/views/app_style/colors.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import 'package:test_sa/views/pages/user/requests/update_service_request_page.dart';
import 'package:test_sa/views/pages/user/requests/work_order/work_orders_list_page.dart';
import 'package:test_sa/views/widgets/images/files_list.dart';
import 'package:test_sa/views/widgets/loaders/app_loading.dart';
@ -54,45 +55,55 @@ class ServiceRequestDetailsPage extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
StatusLabel(
label: serviceRequest.priority.name,
id: serviceRequest.priority.id,
textColor: AColors.getPriorityStatusTextColor(serviceRequest.priority.id),
backgroundColor: AColors.getPriorityStatusColor(serviceRequest.priority.id)),
8.width,
StatusLabel(
label: serviceRequest.statusLabel,
textColor: AColors.getRequestStatusTextColor(serviceRequest.statusValue),
backgroundColor: AColors.getRequestStatusColor(serviceRequest.statusValue)),
1.width.expanded,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
StatusLabel(
label: serviceRequest.priority.name,
id: serviceRequest.priority.id,
textColor: AColors.getPriorityStatusTextColor(serviceRequest.priority.id),
backgroundColor: AColors.getPriorityStatusColor(serviceRequest.priority.id)),
8.width,
StatusLabel(
label: serviceRequest.statusLabel,
textColor: AColors.getRequestStatusTextColor(serviceRequest.statusValue),
backgroundColor: AColors.getRequestStatusColor(serviceRequest.statusValue)),
1.width.expanded,
],
),
8.height,
Text(serviceRequest.deviceEnName, style: AppTextStyles.heading5.copyWith(color: const Color(0xFF3B3D4A))),
8.height,
Text(
'${context.translation.assetNumber}: ${serviceRequest.device.assetNumber}',
style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)),
),
Text(
'Request Type: ${serviceRequest.type.name}',
style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)),
),
Text(
'Request No: ${serviceRequest.requestCode}',
style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)),
),
],
).expanded,
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
if (_userProvider.user.type == UsersTypes.engineer)
if (_userProvider.user.type == UsersTypes.normal_user)
"edit".toSvgAsset(width: 48).onPress(() {
/// todo [zaid] : update service request
Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateServiceRequestPage(serviceRequest: serviceRequest)));
}),
if (_userProvider.user.type == UsersTypes.engineer) 16.height,
Text(serviceRequest.date.toServiceRequestCardFormat, textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: const Color(0xFF3B3D4A))),
],
),
)
],
),
8.height,
Text(serviceRequest.deviceEnName, style: AppTextStyles.heading5.copyWith(color: const Color(0xFF3B3D4A))),
Text(
'${context.translation.assetNumber}: ${serviceRequest.device.assetNumber}',
style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)),
),
Text(
'Request Type: ${serviceRequest.type.name}',
style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)),
),
Text(
'Request No: ${serviceRequest.requestCode}',
style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)),
),
8.height,
const Divider(color: Color(0xFFEAF1F4), height: 1, thickness: 1),
8.height,
Text(
@ -209,7 +220,7 @@ class ServiceRequestDetailsPage extends StatelessWidget {
padding: const EdgeInsets.all(16),
child: informationCard(),
).expanded,
if (_userProvider.user.type != UsersTypes.engineer || (serviceRequest.statusValue == 5 || serviceRequest.statusValue == 3))
if (_userProvider.user.type == UsersTypes.engineer || (serviceRequest.statusValue == 5 || serviceRequest.statusValue == 3))
(serviceRequest.firstAction == null
? AppFilledButton(
label: context.translation.firstAction,

@ -0,0 +1,172 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import '../../../../models/lookup.dart';
import '../../../../new_views/app_style/app_color.dart';
import '../../../../new_views/common_widgets/app_filled_button.dart';
import '../../../../new_views/common_widgets/app_lazy_loading.dart';
import '../../../../new_views/common_widgets/app_text_form_field.dart';
import '../../../../new_views/common_widgets/single_item_drop_down_menu.dart';
import '../../../../providers/service_request_providers/equipment_status_provider.dart';
import '../../../../providers/service_request_providers/priority_provider.dart';
import '../../../../providers/service_request_providers/requested_through_provider.dart';
import '../../../../providers/service_request_providers/type_of_request_provider.dart';
import '../../../widgets/equipment/pick_asset.dart';
import '../../../widgets/images/multi_image_picker.dart';
import '../../../widgets/sound/record_sound.dart';
class UpdateServiceRequestPage extends StatefulWidget {
static const String id = "/update_service_request_page";
final ServiceRequest serviceRequest;
const UpdateServiceRequestPage({Key key, this.serviceRequest}) : super(key: key);
@override
State<UpdateServiceRequestPage> createState() => _UpdateServiceRequestPageState();
}
class _UpdateServiceRequestPageState extends State<UpdateServiceRequestPage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
TextEditingController _commentController;
List<File> _deviceImages = [];
UserProvider _userProvider;
@override
void initState() {
super.initState();
_deviceImages = widget.serviceRequest.devicePhotos.map((e) => File(e)).toList();
_commentController = TextEditingController(text: widget.serviceRequest.callComments ?? "");
}
@override
void dispose() {
_commentController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context, listen: false);
return Scaffold(
appBar: DefaultAppBar(title: context.translation.updateServiceRequest),
body: SafeArea(
child: Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
PickAsset(
editable: false,
device: widget.serviceRequest.device,
onPickAsset: (asset) {
widget.serviceRequest.device = asset;
setState(() {});
},
),
8.height,
SingleItemDropDownMenu<Lookup, PriorityProvider>(
context: context,
title: context.translation.priority,
initialValue: widget.serviceRequest?.priority,
onSelect: (value) {
widget.serviceRequest.priority = value;
},
),
8.height,
SingleItemDropDownMenu<Lookup, EquipmentStatusProvider>(
context: context,
title: context.translation.equipmentStatus,
initialValue: widget.serviceRequest?.defectType,
onSelect: (value) {
widget.serviceRequest.defectType = value;
},
),
8.height,
Consumer<RequestedThroughProvider>(builder: (context, snapshot, _) {
return SingleItemDropDownMenu<Lookup, RequestedThroughProvider>(
context: context,
enabled: false,
title: context.translation.requestedThrough,
initialValue: snapshot.items?.firstWhere((element) => element.value == 3, orElse: () => null),
);
}),
8.height,
SingleItemDropDownMenu<Lookup, TypeOfRequestProvider>(
context: context,
title: context.translation.typeOfRequest,
initialValue: widget.serviceRequest?.type,
onSelect: (value) {
widget.serviceRequest.type = value;
},
),
8.height,
MultiFilesPicker(label: context.translation.attachImage, files: _deviceImages),
((widget.serviceRequest.devicePhotos?.isNotEmpty ?? false) ? 16 : 8).height,
Align(
alignment: AlignmentDirectional.centerStart,
child: context.translation.callComments.heading5(context),
),
8.height,
AppTextFormField(
controller: _commentController,
labelText: context.translation.comments,
initialValue: widget.serviceRequest.callComments,
suffixIcon: "warning".toSvgAsset(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, width: 24).paddingOnly(end: 16),
onSaved: (text) {
widget.serviceRequest.callComments = text;
},
),
8.height,
RecordSound(
onRecord: (audio) {
widget.serviceRequest.audio = audio;
},
enabled: widget.serviceRequest == null ? true : false,
),
16.height,
],
),
).expanded,
AppFilledButton(onPressed: _submit, label: context.translation.updateRequest),
],
),
).paddingOnly(start: 16, end: 16, bottom: 24, top: 16),
),
);
}
Future<void> _submit() async {
widget.serviceRequest?.requestedThrough = Provider.of<RequestedThroughProvider>(context, listen: false).items?.firstWhere((element) => element.value == 3, orElse: () => null);
if (_formKey.currentState.validate() && await widget.serviceRequest.validateNewRequest(context)) {
_formKey.currentState.save();
widget.serviceRequest.devicePhotos = _deviceImages.map((e) => _isLocalUrl(e.path) ? "${e.path.split("/").last}|${base64Encode(e.readAsBytesSync())}" : e.path).toList();
if (widget.serviceRequest.audio != null) {
if (_isLocalUrl(widget.serviceRequest.audio)) {
final File file = File(widget.serviceRequest.audio);
widget.serviceRequest.audio = "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}";
}
}
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
await Provider.of<ServiceRequestsProvider>(context, listen: false).updateRequest(user: _userProvider.user, request: widget.serviceRequest);
Navigator.of(context).pop();
}
}
bool _isLocalUrl(String url) {
if (url?.isEmpty != false) return false;
return url.startsWith("/") || url.startsWith("file://") || url.substring(1).startsWith(':\\');
}
}

@ -1,5 +1,4 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
@ -21,6 +20,7 @@ import 'package:test_sa/providers/work_order/reason_provider.dart';
import 'package:test_sa/providers/work_order/service_type_provider.dart';
import 'package:test_sa/views/widgets/e_signature/e_signature.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/status/report/service_report_assistant_employee_menu.dart';
import 'package:test_sa/views/widgets/status/report/service_report_last_call.dart';
import '../../../../../controllers/providers/api/status_drop_down/report/service_types_provider.dart';
@ -31,7 +31,6 @@ import '../../../../../new_views/common_widgets/default_app_bar.dart';
import '../../../../../new_views/common_widgets/single_item_drop_down_menu.dart';
import '../../../../widgets/date_and_time/date_picker.dart';
import '../../../../widgets/images/multi_image_picker.dart';
import '../../../../widgets/status/report/service_report_assistant_employee_menu.dart';
/// todo : TBD (compare with the design)
class CreateServiceReport extends StatefulWidget {
@ -84,7 +83,7 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
setState(() {});
_serviceReport.callRequest = await _serviceRequestsProvider.getCallRequestForWorkOrder(callId: widget.request.id);
await _assetTypeProvider.getTypes(user: _userProvider.user, host: _settingProvider.host);
// _serviceReport.engineer = Engineer.fromJson(_callRequestForWorkOrder?.assignedEmployee?.toJson());
_serviceReport.assignedEmployee = _serviceReport.callRequest?.assignedEmployee;
_spareParts = await _partsProvider.getPartsList(assetId: widget.request.deviceId);
_isLoading = false;
setState(() {});
@ -180,8 +179,7 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
assetId: _serviceReport.callRequest?.asset?.id,
initialValue: (_serviceReport.assistantEmployees?.isNotEmpty ?? false) ? _serviceReport.assistantEmployees?.first : null,
onSelect: (employee) {
log(employee.toJson().toString());
_serviceReport.assistantEmployees = [employee];
_serviceReport.assistantEmployees = [employee.copyWith(id: 0)];
},
),
8.height,
@ -192,7 +190,7 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
initialValue: (_serviceReport.sparePartsWorkOrders?.isNotEmpty ?? false) ? _serviceReport.sparePartsWorkOrders.first.sparePart : null,
onSelect: (part) {
_serviceReport.sparePartsWorkOrders.clear();
_serviceReport.sparePartsWorkOrders.add(SparePartsWorkOrders(sparePart: part));
_serviceReport.sparePartsWorkOrders.add(SparePartsWorkOrders(id: 0, sparePart: part, qty: 0));
setState(() {});
},
),
@ -201,12 +199,16 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
labelText: context.translation.quantity,
textInputType: TextInputType.number,
enable: _serviceReport.sparePartsWorkOrders.isNotEmpty,
initialValue: (_serviceReport.sparePartsWorkOrders?.isNotEmpty ?? false) ? _serviceReport.sparePartsWorkOrders.first.qty?.toString() : null,
onSaved: (text) {
_serviceReport.sparePartsWorkOrders.first.qty = num.tryParse(text ?? "");
if (_serviceReport.sparePartsWorkOrders?.isNotEmpty ?? false) {
_serviceReport.sparePartsWorkOrders.first.qty = num.tryParse(text ?? "");
}
},
),
8.height,
MultiFilesPicker(label: context.translation.attachImage, files: _files),
8.height,
ESignature(
title: context.translation.engSign,
oldSignature: _serviceReport.engSignature,
@ -227,7 +229,7 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
AppFilledButton(
label: context.translation.submitRequest,
onPressed: () async {
if ((!_formKey.currentState.validate()) || (!(await _serviceReport.validate()))) {
if ((!_formKey.currentState.validate()) || (!(await _serviceReport.validate(context)))) {
setState(() {});
return;
}
@ -235,7 +237,7 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
_serviceReport.attachmentsWorkOrder ??= [];
if (_files.isEmpty) _serviceReport.attachmentsWorkOrder = [];
for (var file in _files) {
_serviceReport.attachmentsWorkOrder.add(Attachment(name: "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}"));
_serviceReport.attachmentsWorkOrder.add(Attachment(id: 0, name: "${file.path.split("/").last}|${base64Encode(file.readAsBytesSync())}"));
}
final user = Provider.of<UserProvider>(context, listen: false).user;
await _serviceRequestsProvider.createServiceReport(context, report: _serviceReport, request: widget.request, user: user);

@ -1,9 +1,5 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/service_requests_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/service_request/search_work_order.dart';
import 'package:test_sa/models/service_request/service_report.dart';
import 'package:test_sa/models/service_request/service_request.dart';
@ -12,29 +8,23 @@ import 'package:test_sa/views/widgets/loaders/failed_loading.dart';
import 'edit_service_report.dart';
class FutureServiceReport extends StatefulWidget {
class UpdateServiceReport extends StatefulWidget {
final ServiceRequest request;
final SearchWorkOrder workOrder;
const FutureServiceReport({Key key, this.request, this.workOrder}) : super(key: key);
const UpdateServiceReport({Key key, this.request, this.workOrder}) : super(key: key);
@override
_FutureServiceReportState createState() => _FutureServiceReportState();
_UpdateServiceReportState createState() => _UpdateServiceReportState();
}
class _FutureServiceReportState extends State<FutureServiceReport> {
UserProvider _userProvider;
SettingProvider _settingProvider;
class _UpdateServiceReportState extends State<UpdateServiceReport> {
@override
Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context);
_settingProvider = Provider.of<SettingProvider>(context);
ServiceRequestsProvider().getSingleServiceReport(reportId: widget.workOrder.id, user: _userProvider.user, host: _settingProvider.host, subtitle: context.translation);
ServiceRequestsProvider().getSingleServiceReport(context, reportId: widget.workOrder.id);
return Scaffold(
body: FutureBuilder<ServiceReport>(
future: ServiceRequestsProvider().getSingleServiceReport(reportId: widget.workOrder.id, user: _userProvider.user, host: _settingProvider.host, subtitle: context.translation),
future: ServiceRequestsProvider().getSingleServiceReport(context, reportId: widget.workOrder.id),
builder: (BuildContext context, AsyncSnapshot<ServiceReport> snapshot) {
if (snapshot.hasError) {
return FailedLoading(
@ -45,10 +35,7 @@ class _FutureServiceReportState extends State<FutureServiceReport> {
);
}
if (snapshot.connectionState == ConnectionState.done) {
return EditServiceReport(
report: snapshot.data,
request: widget.request,
);
return EditServiceReport(report: snapshot.data, request: widget.request);
}
return const Center(child: ALoading());
},

@ -0,0 +1,91 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/service_request/service_request.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import '../../../../../controllers/providers/api/user_provider.dart';
import '../../../../../models/enums/user_types.dart';
import '../../../../../models/service_request/search_work_order.dart';
import '../../../../widgets/requests/request_status.dart';
import 'update_service_report.dart';
class WorkOrderDetailsPage extends StatelessWidget {
static const String id = "/work_order_details_page";
final SearchWorkOrder workOrder;
final ServiceRequest serviceRequest;
const WorkOrderDetailsPage({Key key, this.workOrder, this.serviceRequest}) : super(key: key);
@override
Widget build(BuildContext context) {
UserProvider userProvider = Provider.of<UserProvider>(context);
return Scaffold(
appBar: DefaultAppBar(title: context.translation.workOrder),
body: Column(
children: [
SingleChildScrollView(
child: Container(
margin: const EdgeInsets.all(16),
width: double.infinity,
decoration: ShapeDecoration(
color: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
shadows: const [BoxShadow(color: Color(0x07000000), blurRadius: 14, offset: Offset(0, 0), spreadRadius: 0)],
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
StatusLabel(label: workOrder.currentSituation.name, textColor: AppColor.orange60, backgroundColor: AppColor.orange40),
8.height,
Text(serviceRequest.requestCode, style: AppTextStyles.heading5.copyWith(color: const Color(0xFF3B3D4A))),
8.height,
Text(
'${context.translation.assetName}: ${workOrder.callRequest.asset.modelDefinition.assetName}',
style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)),
),
Text(
'${context.translation.status}: ${workOrder.currentSituation.name}',
style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)),
),
Text(
'${context.translation.orderWorkNumber}: ${workOrder.workOrderNo}',
style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)),
),
Text(
'${context.translation.assignedEmployee}: ${workOrder.assignedEmployee?.name ?? ""}',
style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)),
),
Text('${context.translation.visitDate}: ${workOrder.visitDate?.toServiceRequestDetailsFormat ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))),
Text('${context.translation.assetSN}: ${workOrder.callRequest.asset.assetSerialNo ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))),
Text('${context.translation.assetName}: ${workOrder.callRequest.asset.modelDefinition.assetName ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))),
Text('${context.translation.assetNumber}: ${workOrder.callRequest.asset.assetNumber ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))),
Text('${context.translation.model}: ${workOrder.callRequest.asset.modelDefinition.modelName ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))),
Text('${context.translation.site}: ${workOrder.callRequest.asset.site.custName ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))),
Text('${"Call last Situation"}: ${workOrder.calllastSituation.name ?? '' ?? ""}', style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575))),
],
).paddingAll(16).onPress(() {
// onPressed(request);
}),
),
).expanded,
if (userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3)
AppFilledButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => UpdateServiceReport(request: serviceRequest, workOrder: workOrder)),
);
},
label: context.translation.updateRequest,
).paddingAll(16),
],
),
);
}
}

@ -14,7 +14,8 @@ import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/views/pages/user/requests/work_order/create_service_report.dart';
import 'package:test_sa/views/pages/user/requests/work_order/future_service_report.dart';
import 'package:test_sa/views/pages/user/requests/work_order/update_service_report.dart';
import 'package:test_sa/views/pages/user/requests/work_order/work_order_details_page.dart';
import 'package:test_sa/views/widgets/requests/request_status.dart';
class WorkOrderListPage extends StatelessWidget {
@ -36,14 +37,14 @@ class WorkOrderListPage extends StatelessWidget {
}
print("serviceRequest.statusValue:${serviceRequest.statusValue}");
return Scaffold(
appBar: DefaultAppBar(title: context.translation.workOrder),
appBar: DefaultAppBar(title: context.translation.workOrders),
backgroundColor: const Color(0xfff8f9fb),
body: SafeArea(
child: FutureBuilder(
future: serviceRequestsProvider.searchWorkOrders(callId: serviceRequest.requestCode),
builder: (context, snap) {
workOrders = snap.data as List<SearchWorkOrder>;
if (snap.connectionState == ConnectionState.waiting) return Center(child: CircularProgressIndicator());
if (snap.connectionState == ConnectionState.waiting) return const Center(child: CircularProgressIndicator());
return Column(
children: [
@ -82,14 +83,10 @@ class WorkOrderListPage extends StatelessWidget {
Text(serviceRequest.requestCode, style: AppTextStyles.heading5.copyWith(color: const Color(0xFF3B3D4A))),
],
).expanded,
if (serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3)
if (_userProvider.user.type == UsersTypes.engineer && serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3)
"edit".toSvgAsset(height: 48, width: 48).onPress(() {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => FutureServiceReport(
request: serviceRequest,
workOrder: workOrders[index],
)),
MaterialPageRoute(builder: (_) => UpdateServiceReport(request: serviceRequest, workOrder: workOrders[index])),
);
})
],
@ -104,33 +101,17 @@ class WorkOrderListPage extends StatelessWidget {
children: [
Text(
'${context.translation.assetName}: ${workOrders[index].callRequest.asset.modelDefinition.assetName}',
style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)),
style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)),
),
Text(
'${context.translation.status}: ${workOrders[index].currentSituation.name}',
style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)),
style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF757575)),
),
],
).expanded,
Text(workOrders[index].visitDate?.toServiceRequestCardFormat ?? "", textAlign: TextAlign.end, style: AppTextStyles.tinyFont.copyWith(color: const Color(0xFF3B3D4A))),
],
),
Text(
'${context.translation.orderWorkNumber}: ${workOrders[index].workOrderNo}',
style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)),
),
Text(
'${context.translation.assignedEmployee}: ${workOrders[index].assignedEmployee?.name ?? ""}',
style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575)),
),
Text('${context.translation.assetSN}: ${workOrders[index].callRequest.asset.assetSerialNo ?? ""}', style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))),
Text('${context.translation.assetName}: ${workOrders[index].callRequest.asset.modelDefinition.assetName ?? ""}',
style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))),
Text('${context.translation.assetNumber}: ${workOrders[index].callRequest.asset.assetNumber ?? ""}', style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))),
Text('${context.translation.model}: ${workOrders[index].callRequest.asset.modelDefinition.modelName ?? ""}',
style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))),
Text('${context.translation.site}: ${workOrders[index].callRequest.asset.site.custName ?? ""}', style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))),
Text('${"Call last Situation"}: ${workOrders[index].calllastSituation.name ?? '' ?? ""}', style: AppTextStyles.bodyText.copyWith(color: Color(0xFF757575))),
16.height,
Row(
mainAxisSize: MainAxisSize.min,
@ -140,13 +121,14 @@ class WorkOrderListPage extends StatelessWidget {
style: AppTextStyles.bodyText.copyWith(color: const Color(0xFF4A8DB7)),
),
4.width,
const Icon(
Icons.arrow_forward,
color: Color(0xFF4A8DB7),
size: 14,
)
const Icon(Icons.arrow_forward, color: Color(0xFF4A8DB7), size: 14)
],
),
).onPress(() {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => WorkOrderDetailsPage(workOrder: workOrders[index], serviceRequest: serviceRequest)),
);
}),
],
).paddingAll(16).onPress(() {
// onPressed(request);
@ -156,13 +138,14 @@ class WorkOrderListPage extends StatelessWidget {
);
},
).expanded,
if (_userProvider.user.type != UsersTypes.engineer && (serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3))
if (_userProvider.user.type == UsersTypes.engineer && (serviceRequest.statusValue != 5 && serviceRequest.statusValue != 3))
AppFilledButton(
label: context.translation.createWorkOrder,
maxWidth: true,
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest)));
}).paddingOnly(start: 16, end: 16, bottom: 16)
label: context.translation.createWorkOrder,
maxWidth: true,
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (_) => CreateServiceReport(request: serviceRequest)));
},
).paddingOnly(start: 16, end: 16, bottom: 16)
],
);
},

@ -6,6 +6,9 @@ import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import '../../app_style/sizing.dart';
import '../loaders/image_loader.dart';
class ESignature extends StatefulWidget {
final String oldSignature;
final Uint8List newSignature;
@ -34,8 +37,6 @@ class _ESignatureState extends State<ESignature> {
void initState() {
if (widget.newSignature != null) {
signature = widget.newSignature;
} else if (widget.oldSignature != null || signature != null) {
signature = widget.oldSignature.codeUnits;
}
super.initState();
}
@ -50,12 +51,13 @@ class _ESignatureState extends State<ESignature> {
Widget build(BuildContext context) {
return Column(
children: [
// if (widget.oldSignature != null || signature != null)
// Container(
// width: MediaQuery.of(context).size.width,
// padding: const EdgeInsets.only(bottom: 8),
// height: 90 * AppStyle.getScaleFactor(context),
// child: signature != null ? Image.memory(signature) : ImageLoader(boxFit: BoxFit.contain, url: widget.oldSignature)),
if (widget.oldSignature != null || signature != null)
Container(
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.only(bottom: 8),
height: 90 * AppStyle.getScaleFactor(context),
child: signature != null ? Image.memory(signature) : ImageLoader(boxFit: BoxFit.contain, url: widget.oldSignature),
),
FormField<String>(onSaved: (_) async {
widget.onSaved(signature);
}, builder: (FormFieldState<String> state) {

@ -12,36 +12,38 @@ import '../../../new_views/common_widgets/asset_info_card.dart';
class PickAsset extends StatelessWidget {
final Function(Asset) onPickAsset;
final Asset device;
final bool editable;
const PickAsset({Key key, this.device, this.onPickAsset}) : super(key: key);
const PickAsset({Key key, this.editable = true, this.device, this.onPickAsset}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
children: [
Container(
decoration: BoxDecoration(
color: Theme.of(context).cardColor,
borderRadius: BorderRadius.circular(10),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)],
if (editable)
Container(
decoration: BoxDecoration(
color: Theme.of(context).cardColor,
borderRadius: BorderRadius.circular(10),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)],
),
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight),
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
context.translation.device.tinyFont(context).custom(color: context.isDark ? AppColor.neutral40 : AppColor.neutral50),
context.translation.pickAsset.bodyText(context).custom(color: context.isDark ? AppColor.neutral40 : AppColor.neutral50),
],
).onPress(() async {
Asset device = await Navigator.of(context).pushNamed(SingleDevicePicker.id) as Asset;
onPickAsset(device);
}).expanded,
"qr".toSvgAsset(height: 24, fit: BoxFit.fitHeight, color: context.isDark ? AppColor.primary40 : AppColor.primary70),
],
),
),
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight),
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
context.translation.device.tinyFont(context).custom(color: context.isDark ? AppColor.neutral40 : AppColor.neutral50),
context.translation.pickAsset.bodyText(context).custom(color: context.isDark ? AppColor.neutral40 : AppColor.neutral50),
],
).onPress(() async {
Asset device = await Navigator.of(context).pushNamed(SingleDevicePicker.id) as Asset;
onPickAsset(device);
}).expanded,
"qr".toSvgAsset(height: 24, fit: BoxFit.fitHeight, color: context.isDark ? AppColor.primary40 : AppColor.primary70),
],
),
),
if (device != null) AssetInfoCard(asset: device).paddingOnly(top: 8),
],
);

Loading…
Cancel
Save