Merge branch 'main_latest_merged' into zaid_development_new

# Conflicts:
#	lib/controllers/providers/api/service_requests_provider.dart
#	lib/models/service_report.dart
#	lib/views/pages/user/requests/report/create_service_report.dart
merge-requests/31/head
zaid_daoud 3 years ago
commit 47b1a0ff36

@ -319,15 +319,15 @@ class ServiceRequestsProvider extends ChangeNotifier {
"reason": report.reason?.toMap(), "reason": report.reason?.toMap(),
"startofWorkTime": report.startDate?.toIso8601String() ?? "", "startofWorkTime": report.startDate?.toIso8601String() ?? "",
"endofWorkTime": report.endDate?.toIso8601String() ?? "", "endofWorkTime": report.endDate?.toIso8601String() ?? "",
"workingHours": report.timer?.durationInSecond, "workingHours": ((report?.endDate?.difference(report?.startDate)?.inMinutes ?? 0) / 60),
"travelingHours": report.travelingHours, "travelingHours": report.travelingHours,
"travelingExpenses": report.travelingExpense ?? 0, "travelingExpenses": report.travelingExpense ?? 0,
if (report.faultDescription != null) "faultDescription": report.faultDescription.toJson(), if (report.faultDescription != null) "faultDescription": report.faultDescription.toJson(),
"sparePartsWorkOrders": report.parts "sparePartsWorkOrders": report.parts
?.map( ?.map(
(p) => { (p) => {
"id": p.id, "id": p.reportPartID ?? 0,
"sparePart": {"id": p.reportPartID ?? 0, "partNo": p.code, "partName": p.name}, "sparePart": {"id": p.id, "partNo": p.code, "partName": p.name},
"qty": p.quantity "qty": p.quantity
}, },
) )

@ -11,7 +11,7 @@ import 'package:test_sa/models/timer_model.dart';
class ServiceReport { class ServiceReport {
int id; int id;
String operatingHours; double operatingHours;
DateTime visitDate; DateTime visitDate;
DateTime endDate; DateTime endDate;
DateTime startDate; DateTime startDate;
@ -26,7 +26,7 @@ class ServiceReport {
String workPreformed; String workPreformed;
//String workHours; //String workHours;
String travelingHours; double travelingHours;
String invoiceNumber; String invoiceNumber;
String invoiceCode; String invoiceCode;
List<Part> parts; List<Part> parts;
@ -93,7 +93,14 @@ class ServiceReport {
_map["endofWorkTime"] = (timer.endAt ?? DateTime.now()).toIso8601String(); _map["endofWorkTime"] = (timer.endAt ?? DateTime.now()).toIso8601String();
_map["workingHours"] = (timer.durationInSecond / 60 / 60).toStringAsFixed(5); _map["workingHours"] = (timer.durationInSecond / 60 / 60).toStringAsFixed(5);
} }
if (travelingHours != null && travelingHours.isNotEmpty) _map["traveling_hours"] = travelingHours; if (travelingHours != null && travelingHours.toString().isNotEmpty) _map["traveling_hours"] = travelingHours;
// if(workPreformed != null && workPreformed.isNotEmpty){
// _map["faultDescription"] = {
// //"id":faultDescriptionId ?? 0,
// "workPerformed":workPreformed
// };
// }
if (travelingHours != null) _map["traveling_hours"] = travelingHours;
if (workPreformed != null && workPreformed.isNotEmpty) { if (workPreformed != null && workPreformed.isNotEmpty) {
_map["faultDescription"] = faultDescription.toJson(); _map["faultDescription"] = faultDescription.toJson();
} }
@ -170,7 +177,7 @@ class ServiceReport {
reason: Lookup.fromJson(parsedJson["reason"]), reason: Lookup.fromJson(parsedJson["reason"]),
status: Lookup.fromJson(parsedJson["status"]), status: Lookup.fromJson(parsedJson["status"]),
type: Lookup.fromJson(parsedJson["typeOfWO"]), type: Lookup.fromJson(parsedJson["typeOfWO"]),
//faultDescriptionId: parsedJson["fault_description"], faultDescriptionId: parsedJson["fault_description"],
endDate: DateTime.tryParse(parsedJson["endofWorkTime"]), endDate: DateTime.tryParse(parsedJson["endofWorkTime"]),
//invoiceCode: parsedJson["invoice_code"], //invoiceCode: parsedJson["invoice_code"],
//invoiceNumber: parsedJson["invoice_no"], //invoiceNumber: parsedJson["invoice_no"],

@ -28,14 +28,16 @@ import 'package:test_sa/views/widgets/images/mini_one_image_picker.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart'; import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import 'package:test_sa/views/widgets/parts/auto_complete_parts_field.dart'; import 'package:test_sa/views/widgets/parts/auto_complete_parts_field.dart';
import 'package:test_sa/views/widgets/parts/part_item.dart'; import 'package:test_sa/views/widgets/parts/part_item.dart';
import 'package:test_sa/views/widgets/status/employee/engineers_mune.dart';
import 'package:test_sa/views/widgets/status/report/service_report_last_call.dart'; import 'package:test_sa/views/widgets/status/report/service_report_last_call.dart';
import 'package:test_sa/views/widgets/status/report/service_report_reasons.dart'; import 'package:test_sa/views/widgets/status/report/service_report_reasons.dart';
import 'package:test_sa/views/widgets/status/report/service_report_status.dart'; import 'package:test_sa/views/widgets/status/report/service_report_status.dart';
import 'package:test_sa/views/widgets/status/report/service_status.dart';
import 'package:test_sa/views/widgets/timer/app_timer.dart';
import 'package:test_sa/views/widgets/titles/app_sub_title.dart'; import 'package:test_sa/views/widgets/titles/app_sub_title.dart';
import '../../../../../controllers/providers/api/status_drop_down/report/service_types_provider.dart'; import '../../../../../controllers/providers/api/status_drop_down/report/service_types_provider.dart';
import '../../../../widgets/speech_to_text/speech_to_text.dart'; import '../../../../widgets/speech_to_text/speech_to_text.dart';
import '../../../../widgets/status/report/service_report_fault_description.dart';
import '../../../../widgets/status/report/service_report_repair_location.dart'; import '../../../../widgets/status/report/service_report_repair_location.dart';
class CreateServiceReport extends StatefulWidget { class CreateServiceReport extends StatefulWidget {
@ -122,22 +124,22 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
), ),
), ),
), ),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ASubTitle("Caller Info"),
const SizedBox(height: 8),
Container( Container(
padding: const EdgeInsets.symmetric(horizontal: 16), width: double.infinity,
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [ margin: const EdgeInsets.symmetric(vertical: 16),
const BoxShadow( decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: const [
BoxShadow(
color: AColors.grey, color: AColors.grey,
offset: Offset(0, -1), offset: Offset(0, -1),
) )
]), ]),
child: Column( child: Wrap(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 8,
),
Wrap(
spacing: 10, spacing: 10,
children: [ children: [
ASubTitle( ASubTitle(
@ -160,8 +162,261 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
) )
], ],
), ),
const Divider(), ),
ASubTitle("Work Order Details"),
Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
margin: const EdgeInsets.symmetric(vertical: 16),
decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [
BoxShadow(
color: AColors.grey,
offset: Offset(0, -1),
),
]),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Report type and Reasons
Row(
children: [
// Report Status
// Expanded(
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// ASubTitle(_subtitle.reportType),
// _validate && _serviceReport.type == null ?
// ASubTitle(_subtitle.requiredWord,color: Colors.red,):
// const SizedBox.shrink(),
// const SizedBox(height: 4,),
// ServiceReportTypeMenu(
// initialValue: _serviceReport.type,
// onSelect: (status){
// _serviceReport.type = status;
// },
// ),
// ],
// ),
// ),
// 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(),
Row(
children: [
Expanded(
child: ADatePicker(
date: _serviceReport.visitDate,
from: DateTime.now().subtract(const Duration(days: 365)),
to: DateTime.now().add(const Duration(days: 365)),
onDatePicker: (date) {
_serviceReport.visitDate = date;
setState(() {});
},
),
),
],
),
],
),
),
],
),
const SizedBox(
height: 8,
),
// device sn
Visibility(
visible: widget.request.deviceSerialNumber == null,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ASubTitle(_subtitle.deviceSN),
_validate && _serviceReport.device?.id == null
? ASubTitle(
_subtitle.requiredWord,
color: Colors.red,
)
: const SizedBox.shrink(),
AutoCompleteDeviceField(
hospitalId: widget.request.hospitalId,
initialValue: _serviceReport.device,
onPick: (id) {
_serviceReport.device.id = id;
},
),
const SizedBox(
height: 8,
),
],
),
),
const SizedBox(
height: 8,
),
ASubTitle(_subtitle.serviceType),
_validate && _serviceReport.assetType == null
? ASubTitle(
_subtitle.requiredWord,
color: Colors.red,
)
: const SizedBox.shrink(),
const SizedBox(
height: 4,
),
ServiceAssetTypeMenu(
initialValue: _serviceReport.assetType,
onSelect: (status) {
_serviceReport.assetType = status;
},
),
const SizedBox(
height: 8,
),
// Report status and Service Type
Row(
children: [
// report status
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ASubTitle(_subtitle.reportStatus),
_validate && _serviceReport.status == null
? ASubTitle(
_subtitle.requiredWord,
color: Colors.red,
)
: const SizedBox.shrink(),
const SizedBox(
height: 4,
),
ServiceReportStatusMenu(
report: _serviceReport,
request: widget.request,
onSelect: (status) {
_serviceReport.status = status;
},
),
],
),
),
const SizedBox(
width: 8,
),
// Provider.of<ServiceReportLastCallsProvider>(context).isLoading == null
// ? const SizedBox.shrink():
// Call's last Situation
Consumer<ServiceReportLastCallsProvider>(
builder: (_, provider, __) {
if (provider.isLoading == null) return const SizedBox.shrink();
return Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ASubTitle(_subtitle.callLastSituation),
_validate && _serviceReport.callLastSituation == null
? ASubTitle(
_subtitle.requiredWord,
color: Colors.red,
)
: const SizedBox.shrink(),
const SizedBox(
height: 4,
),
ServiceReportLastCallsMenu(
report: _serviceReport,
onSelect: (status) {
if (status?.value == 12 || _serviceReport.callLastSituation?.value == 12) {
_serviceReport.callLastSituation = status;
setState(() {});
} else {
_serviceReport.callLastSituation = status;
}
},
),
],
),
);
},
),
],
),
SizedBox(
height: 8 * AppStyle.getScaleFactor(context),
),
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const ASubTitle("Start of Work"),
SizedBox(
height: 8 * AppStyle.getScaleFactor(context),
),
ADateTimePicker(
date: _serviceReport.startDate,
from: DateTime.now().subtract(const Duration(days: 365)),
to: DateTime.now().add(const Duration(days: 365)),
onDateTimePicker: (date) {
_serviceReport.startDate = date;
setState(() {});
},
),
],
),
),
const SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const ASubTitle("End of Work"),
SizedBox(
height: 8 * AppStyle.getScaleFactor(context),
),
ADateTimePicker(
date: _serviceReport.endDate,
from: DateTime.now().subtract(const Duration(days: 365)),
to: DateTime.now().add(const Duration(days: 365)),
onDateTimePicker: (date) {
_serviceReport.endDate = date;
setState(() {});
},
),
],
),
),
],
),
ASubTitle(_subtitle.workingHours),
const SizedBox(height: 4),
ATextFormField(
initialValue: null,
textAlign: TextAlign.center,
hintText: _serviceReport.startDate == null
? "0"
: ((_serviceReport?.endDate?.difference(_serviceReport?.startDate)?.inMinutes ?? 0) / 60)?.toStringAsFixed(2)?.toString() ?? "0",
enable: false,
style: Theme.of(context).textTheme.subtitle1,
validator: (value) => Validator.isNumeric(value) ? null : _subtitle.requiredWord,
textInputType: TextInputType.number,
onSaved: (value) {
// _serviceReport.workHours = value;
},
),
// Report type and Reasons // Report type and Reasons
Row( Row(
children: [ children: [
@ -439,6 +694,128 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
SizedBox( SizedBox(
height: 8 * AppStyle.getScaleFactor(context), height: 8 * AppStyle.getScaleFactor(context),
), ),
const ASubTitle("Assigned Employee"),
const SizedBox(height: 8),
_validate && _serviceReport.engineer == null
? ASubTitle(
_subtitle.requiredWord,
color: Colors.red,
)
: const SizedBox.shrink(),
const SizedBox(height: 4),
EngineersMenu(
initialValue: _serviceReport.engineer,
onSelect: (engineer) {
_serviceReport.engineer = engineer;
},
),
const SizedBox(height: 8),
// invoice number & code
_serviceReport.callLastSituation?.id != 12
? const SizedBox.shrink()
: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ASubTitle(_subtitle.invoiceNumber),
const SizedBox(
height: 8,
),
ATextFormField(
initialValue: _serviceReport?.invoiceNumber,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle1,
validator: (value) => Validator.hasValue(value) ? null : _subtitle.requiredWord,
textInputType: TextInputType.number,
onSaved: (value) {
_serviceReport.invoiceNumber = value;
},
),
],
),
),
const SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ASubTitle(_subtitle.invoiceCode),
const SizedBox(height: 4),
ATextFormField(
initialValue: _serviceReport?.invoiceCode,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subtitle1,
validator: (value) => Validator.hasValue(value) ? null : _subtitle.requiredWord,
textInputType: TextInputType.text,
onSaved: (value) {
_serviceReport.invoiceCode = value;
},
),
],
),
),
],
),
const SizedBox(height: 8),
Row(
children: [
ASubTitle(_subtitle.faultDescription),
Expanded(
child: SizedBox(
height: 32 * AppStyle.getScaleFactor(context),
child: SpeechToTextButton(
controller: _faultController,
mini: true,
),
),
),
],
),
const SizedBox(height: 4),
ATextFormField(
initialValue: _serviceReport?.faultDescriptionId?.toString(),
textAlign: TextAlign.center,
controller: _faultController,
style: Theme.of(context).textTheme.titleMedium,
validator: (value) => Validator.hasValue(value) ? null : _subtitle.requiredWord,
textInputType: TextInputType.multiline,
onSaved: (value) {
_serviceReport.faultDescriptionId = int.tryParse(value) ?? 0;
},
),
const SizedBox(height: 8),
Row(
children: [
ASubTitle(_subtitle.workPreformed),
Expanded(
child: SizedBox(
height: 32 * AppStyle.getScaleFactor(context),
child: SpeechToTextButton(
controller: _workPreformedController,
mini: true,
),
),
),
],
),
const SizedBox(height: 4),
ATextFormField(
initialValue: _serviceReport?.workPreformed,
textAlign: TextAlign.center,
controller: _workPreformedController,
style: Theme.of(context).textTheme.subtitle1,
validator: (value) => Validator.hasValue(value) ? null : _subtitle.requiredWord,
textInputType: TextInputType.multiline,
onSaved: (value) {
_serviceReport.workPreformed = value;
},
),
const SizedBox(height: 8),
SizedBox(
height: 8 * AppStyle.getScaleFactor(context),
),
// const ASubTitle("Assigned Employee"), // const ASubTitle("Assigned Employee"),
// const SizedBox( // const SizedBox(
// height: 8, // height: 8,
@ -575,9 +952,7 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
height: 8, height: 8,
), ),
const SizedBox( const SizedBox(height: 8),
height: 8,
),
Row( Row(
children: [ children: [
// reasons // reasons
@ -586,9 +961,7 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
ASubTitle(_subtitle.reasons), ASubTitle(_subtitle.reasons),
const SizedBox( const SizedBox(height: 4),
height: 4,
),
ServiceReportReasonsMenu( ServiceReportReasonsMenu(
initialValue: _serviceReport.reason, initialValue: _serviceReport.reason,
onSelect: (status) { onSelect: (status) {
@ -598,9 +971,7 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
], ],
), ),
), ),
const SizedBox( const SizedBox(width: 8),
width: 8,
),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -619,22 +990,16 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
), ),
], ],
), ),
const SizedBox( const SizedBox(height: 8),
height: 8,
),
ASubTitle(_subtitle.repairLocation), ASubTitle(_subtitle.repairLocation),
const SizedBox( const SizedBox(height: 4),
height: 4,
),
ServiceReportRepairLocation( ServiceReportRepairLocation(
initialValue: _serviceReport.repairLocation, initialValue: _serviceReport.repairLocation,
onSelect: (status) { onSelect: (status) {
_serviceReport.repairLocation = status; _serviceReport.repairLocation = status;
}, },
), ),
const SizedBox( const SizedBox(height: 16),
height: 16,
),
ASubTitle(_subtitle.travelingExpense), ASubTitle(_subtitle.travelingExpense),
const SizedBox( const SizedBox(
height: 4, height: 4,
@ -703,7 +1068,7 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
height: 4, height: 4,
), ),
ATextFormField( ATextFormField(
initialValue: _serviceReport?.travelingHours, initialValue: _serviceReport?.travelingHours?.toString(),
textAlign: TextAlign.center, textAlign: TextAlign.center,
hintText: "i.e 3, 3.5, 4", hintText: "i.e 3, 3.5, 4",
style: Theme.of(context).textTheme.subtitle1, style: Theme.of(context).textTheme.subtitle1,
@ -712,7 +1077,7 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
// ? null : _subtitle.requiredWord, // ? null : _subtitle.requiredWord,
textInputType: TextInputType.number, textInputType: TextInputType.number,
onSaved: (value) { onSaved: (value) {
_serviceReport.travelingHours = value; _serviceReport.travelingHours = double.tryParse(value) ?? 0.0;
}, },
), ),
], ],
@ -770,13 +1135,9 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
// ], // ],
// ), // ),
const SizedBox( const SizedBox(height: 8),
height: 8,
),
ASubTitle(_subtitle.comment), ASubTitle(_subtitle.comment),
const SizedBox( const SizedBox(height: 4),
height: 4,
),
ATextFormField( ATextFormField(
initialValue: _serviceReport?.comment, initialValue: _serviceReport?.comment,
hintText: "Technical Comment", hintText: "Technical Comment",
@ -800,9 +1161,7 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
_serviceReport.signatureNurse = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"; _serviceReport.signatureNurse = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
}, },
), ),
const SizedBox( const SizedBox(height: 8),
height: 8,
),
const ASubTitle("Engineer Signature"), const ASubTitle("Engineer Signature"),
ESignature( ESignature(
oldSignature: _serviceReport.signatureEngineer, oldSignature: _serviceReport.signatureEngineer,
@ -818,7 +1177,25 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
const SizedBox( const SizedBox(
height: 8, height: 8,
), ),
],
),
),
// Part Number and Quantity // Part Number and Quantity
ASubTitle("Spare Parts"),
Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
margin: const EdgeInsets.symmetric(vertical: 16),
decoration: BoxDecoration(color: AColors.grey, borderRadius: BorderRadius.circular(AppStyle.getBorderRadius(context)), boxShadow: [
BoxShadow(
color: AColors.grey,
offset: Offset(0, -1),
)
]),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row( Row(
children: [ children: [
Expanded( Expanded(
@ -873,16 +1250,16 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
], ],
), ),
), ),
Padding( ],
padding: const EdgeInsets.all(16.0), ),
child: AButton( AButton(
text: _subtitle.submit, text: _subtitle.submit,
onPressed: () async { onPressed: () async {
_validate = true; _validate = true;
if (!_formKey.currentState.validate()) { // if (!_formKey.currentState.validate()) {
setState(() {}); // setState(() {});
return; // return;
} // }
if (!_serviceReport.validate()) return; if (!_serviceReport.validate()) return;
_formKey.currentState.save(); _formKey.currentState.save();
@ -913,7 +1290,6 @@ class _CreateServiceReportState extends State<CreateServiceReport> with TickerPr
} }
}, },
), ),
),
const SizedBox( const SizedBox(
height: 300, height: 300,
) )

Loading…
Cancel
Save