Compare commits
4 Commits
09843a9625
...
a04ae0c833
| Author | SHA1 | Date |
|---|---|---|
|
|
a04ae0c833 | 2 weeks ago |
|
|
81dd189025 | 3 weeks ago |
|
|
81dd799672 | 4 weeks ago |
|
|
a8e8774040 | 4 weeks ago |
@ -0,0 +1,3 @@
|
||||
<svg width="17" height="20" viewBox="0 0 17 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.82353 1.94999C3.67937 1.94999 1.94118 3.69608 1.94118 5.84998V11.2125C1.94118 14.7126 4.76573 17.55 8.25 17.55C11.7343 17.55 14.5588 14.7126 14.5588 11.2125V9.75003C14.5588 9.21155 14.9934 8.77503 15.5294 8.77503C16.0655 8.77503 16.5 9.21155 16.5 9.75003V11.2125C16.5 15.7896 12.8063 19.5 8.25 19.5C3.69365 19.5 0 15.7896 0 11.2125V5.84998C0 2.61913 2.60728 0 5.82353 0C9.03978 0 11.6471 2.61913 11.6471 5.84998V11.2125C11.6471 13.0971 10.1261 14.625 8.25 14.625C6.37386 14.625 4.85294 13.0971 4.85294 11.2125V7.31248C4.85294 6.774 5.28749 6.33748 5.82353 6.33748C6.35957 6.33748 6.79412 6.774 6.79412 7.31248V11.2125C6.79412 12.0202 7.44594 12.675 8.25 12.675C9.05406 12.675 9.70588 12.0202 9.70588 11.2125V5.84998C9.70588 3.69608 7.96769 1.94999 5.82353 1.94999Z" fill="#3DA5E5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 938 B |
@ -0,0 +1,53 @@
|
||||
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
|
||||
|
||||
class EngineerData {
|
||||
int? id;
|
||||
String? debrief;
|
||||
String? startTime;
|
||||
String? endTime;
|
||||
double? totalHours;
|
||||
bool? isComplete;
|
||||
int? statusId;
|
||||
int? requestId;
|
||||
List<InternalAuditAttachments>? attachments;
|
||||
|
||||
EngineerData({
|
||||
this.id,
|
||||
this.debrief,
|
||||
this.startTime,
|
||||
this.endTime,
|
||||
this.totalHours,
|
||||
this.isComplete,
|
||||
this.statusId,
|
||||
this.requestId,
|
||||
this.attachments,
|
||||
});
|
||||
|
||||
EngineerData.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
debrief = json['debrief'];
|
||||
startTime = json['startTime'];
|
||||
endTime = json['endTime'];
|
||||
totalHours = (json['totalHours'] as num?)?.toDouble();
|
||||
isComplete = json['isComplete'];
|
||||
statusId = json['statusId'];
|
||||
requestId = json['requestId'];
|
||||
attachments = json['attachments'] != null ? (json['attachments'] as List).map((e) => InternalAuditAttachments.fromJson(e)).toList() : [];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = {};
|
||||
data['id'] = id;
|
||||
data['debrief'] = debrief;
|
||||
data['startTime'] = startTime;
|
||||
data['endTime'] = endTime;
|
||||
data['totalHours'] = totalHours;
|
||||
data['isComplete'] = isComplete;
|
||||
data['statusId'] = statusId;
|
||||
data['requestId'] = requestId;
|
||||
if (attachments != null) {
|
||||
data['attachments'] = attachments!.map((e) => e.toJson()).toList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,300 @@
|
||||
import 'package:test_sa/models/timer_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/engineer_data_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_timer_model.dart';
|
||||
|
||||
class EquipmentInternalAuditDataModel {
|
||||
int? id;
|
||||
String? requestNo;
|
||||
String? createdDate;
|
||||
int? requestNoSequence;
|
||||
Auditor? auditor;
|
||||
Status? status;
|
||||
Asset? asset;
|
||||
AssignEmployee? assignEmployee;
|
||||
dynamic manufacture;
|
||||
String? remarks;
|
||||
List<EquipmentsFinding>? equipmentsFindings;
|
||||
List<InternalAuditAttachments>? attachments;
|
||||
EngineerData? engineerData;
|
||||
|
||||
|
||||
EquipmentInternalAuditDataModel({
|
||||
this.id,
|
||||
this.requestNo,
|
||||
this.createdDate,
|
||||
this.requestNoSequence,
|
||||
this.auditor,
|
||||
this.status,
|
||||
this.asset,
|
||||
this.assignEmployee,
|
||||
this.manufacture,
|
||||
this.remarks,
|
||||
this.equipmentsFindings,
|
||||
this.attachments,
|
||||
this.engineerData,
|
||||
});
|
||||
|
||||
EquipmentInternalAuditDataModel.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
requestNo = json['requestNo'];
|
||||
createdDate = json['createdDate'];
|
||||
requestNoSequence = json['requestNoSequence'];
|
||||
auditor = json['auditor'] != null ? Auditor.fromJson(json['auditor']) : null;
|
||||
status = json['status'] != null ? Status.fromJson(json['status']) : null;
|
||||
asset = json['asset'] != null ? Asset.fromJson(json['asset']) : null;
|
||||
assignEmployee = json['assignEmployee'] != null ? AssignEmployee.fromJson(json['assignEmployee']) : null;
|
||||
manufacture = json['manufacture'];
|
||||
remarks = json['remarks'];
|
||||
if (json['equipmentsFindings'] != null) {
|
||||
equipmentsFindings = <EquipmentsFinding>[];
|
||||
json['equipmentsFindings'].forEach((v) {
|
||||
equipmentsFindings!.add(EquipmentsFinding.fromJson(v));
|
||||
});
|
||||
}
|
||||
attachments = json['attachments'] != null
|
||||
? (json['attachments'] as List)
|
||||
.map((e) => InternalAuditAttachments.fromJson(e))
|
||||
.where((e) => e.name != null) // optional filter if you want to skip null names
|
||||
.toList()
|
||||
: [];
|
||||
engineerData = json['engineerData'] != null ? EngineerData.fromJson(json['engineerData']) : null;
|
||||
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = {};
|
||||
data['id'] = id;
|
||||
data['requestNo'] = requestNo;
|
||||
data['createdDate'] = createdDate;
|
||||
data['requestNoSequence'] = requestNoSequence;
|
||||
if (auditor != null) {
|
||||
data['auditor'] = auditor!.toJson();
|
||||
}
|
||||
if (status != null) {
|
||||
data['status'] = status!.toJson();
|
||||
}
|
||||
if (asset != null) {
|
||||
data['asset'] = asset!.toJson();
|
||||
}
|
||||
if (assignEmployee != null) {
|
||||
data['assignEmployee'] = assignEmployee!.toJson();
|
||||
}
|
||||
data['manufacture'] = manufacture;
|
||||
data['remarks'] = remarks;
|
||||
if (equipmentsFindings != null) {
|
||||
data['equipmentsFindings'] =
|
||||
equipmentsFindings!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
data['attachments'] = attachments;
|
||||
if (engineerData != null) data['engineerData'] = engineerData!.toJson();
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Auditor {
|
||||
String? userId;
|
||||
String? userName;
|
||||
String? email;
|
||||
String? employeeId;
|
||||
int? languageId;
|
||||
String? extensionNo;
|
||||
String? phoneNumber;
|
||||
bool? isActive;
|
||||
|
||||
Auditor({
|
||||
this.userId,
|
||||
this.userName,
|
||||
this.email,
|
||||
this.employeeId,
|
||||
this.languageId,
|
||||
this.extensionNo,
|
||||
this.phoneNumber,
|
||||
this.isActive,
|
||||
});
|
||||
|
||||
Auditor.fromJson(Map<String, dynamic> json) {
|
||||
userId = json['userId'];
|
||||
userName = json['userName'];
|
||||
email = json['email'];
|
||||
employeeId = json['employeeId'];
|
||||
languageId = json['languageId'];
|
||||
extensionNo = json['extensionNo'];
|
||||
phoneNumber = json['phoneNumber'];
|
||||
isActive = json['isActive'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = {};
|
||||
data['userId'] = userId;
|
||||
data['userName'] = userName;
|
||||
data['email'] = email;
|
||||
data['employeeId'] = employeeId;
|
||||
data['languageId'] = languageId;
|
||||
data['extensionNo'] = extensionNo;
|
||||
data['phoneNumber'] = phoneNumber;
|
||||
data['isActive'] = isActive;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Status {
|
||||
int? id;
|
||||
String? name;
|
||||
int? value;
|
||||
|
||||
Status({this.id, this.name, this.value});
|
||||
|
||||
Status.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
name = json['name'];
|
||||
value = json['value'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = {};
|
||||
data['id'] = id;
|
||||
data['name'] = name;
|
||||
data['value'] = value;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Asset {
|
||||
int? id;
|
||||
String? assetNumber;
|
||||
String? assetSerialNo;
|
||||
String? assetName;
|
||||
String? modelName;
|
||||
String? manufacturerName;
|
||||
String? siteName;
|
||||
int? siteId;
|
||||
String? modelDefinition;
|
||||
|
||||
Asset({
|
||||
this.id,
|
||||
this.assetNumber,
|
||||
this.assetSerialNo,
|
||||
this.assetName,
|
||||
this.modelName,
|
||||
this.manufacturerName,
|
||||
this.siteName,
|
||||
this.siteId,
|
||||
this.modelDefinition,
|
||||
});
|
||||
|
||||
Asset.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
assetNumber = json['assetNumber'];
|
||||
assetSerialNo = json['assetSerialNo'];
|
||||
assetName = json['assetName'];
|
||||
modelName = json['modelName'];
|
||||
manufacturerName = json['manufacturerName'];
|
||||
siteName = json['siteName'];
|
||||
siteId = json['siteId'];
|
||||
modelDefinition = json['modelDefinition'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = {};
|
||||
data['id'] = id;
|
||||
data['assetNumber'] = assetNumber;
|
||||
data['assetSerialNo'] = assetSerialNo;
|
||||
data['assetName'] = assetName;
|
||||
data['modelName'] = modelName;
|
||||
data['manufacturerName'] = manufacturerName;
|
||||
data['siteName'] = siteName;
|
||||
data['siteId'] = siteId;
|
||||
data['modelDefinition'] = modelDefinition;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class AssignEmployee {
|
||||
String? userId;
|
||||
String? userName;
|
||||
String? email;
|
||||
String? employeeId;
|
||||
int? languageId;
|
||||
String? extensionNo;
|
||||
String? phoneNumber;
|
||||
bool? isActive;
|
||||
|
||||
AssignEmployee({
|
||||
this.userId,
|
||||
this.userName,
|
||||
this.email,
|
||||
this.employeeId,
|
||||
this.languageId,
|
||||
this.extensionNo,
|
||||
this.phoneNumber,
|
||||
this.isActive,
|
||||
});
|
||||
|
||||
AssignEmployee.fromJson(Map<String, dynamic> json) {
|
||||
userId = json['userId'];
|
||||
userName = json['userName'];
|
||||
email = json['email'];
|
||||
employeeId = json['employeeId'];
|
||||
languageId = json['languageId'];
|
||||
extensionNo = json['extensionNo'];
|
||||
phoneNumber = json['phoneNumber'];
|
||||
isActive = json['isActive'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = {};
|
||||
data['userId'] = userId;
|
||||
data['userName'] = userName;
|
||||
data['email'] = email;
|
||||
data['employeeId'] = employeeId;
|
||||
data['languageId'] = languageId;
|
||||
data['extensionNo'] = extensionNo;
|
||||
data['phoneNumber'] = phoneNumber;
|
||||
data['isActive'] = isActive;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class EquipmentsFinding {
|
||||
int? id;
|
||||
Finding? finding;
|
||||
|
||||
EquipmentsFinding({this.id, this.finding});
|
||||
|
||||
EquipmentsFinding.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
finding = json['finding'] != null ? Finding.fromJson(json['finding']) : null;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = {};
|
||||
data['id'] = id;
|
||||
if (finding != null) {
|
||||
data['finding'] = finding!.toJson();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Finding {
|
||||
int? id;
|
||||
String? name;
|
||||
int? value;
|
||||
|
||||
Finding({this.id, this.name, this.value});
|
||||
|
||||
Finding.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
name = json['name'];
|
||||
value = json['value'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = {};
|
||||
data['id'] = id;
|
||||
data['name'] = name;
|
||||
data['value'] = value;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:test_sa/controllers/api_routes/urls.dart';
|
||||
import 'package:test_sa/extensions/context_extension.dart';
|
||||
import 'package:test_sa/models/device/asset.dart';
|
||||
import 'package:test_sa/models/fault_description.dart';
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
|
||||
|
||||
class EquipmentInternalAuditFormModel {
|
||||
int? id=0;
|
||||
String? deviceArName;
|
||||
String? auditorId;
|
||||
String? woOrderNo;
|
||||
List<String>? devicePhotos;
|
||||
List<Lookup> findings =[];
|
||||
List<InternalAuditAttachments> attachments = [];
|
||||
String? remarks;
|
||||
Asset? device;
|
||||
EquipmentInternalAuditFormModel({
|
||||
this.id,
|
||||
this.deviceArName,
|
||||
this.auditorId,
|
||||
this.devicePhotos,
|
||||
this.woOrderNo,
|
||||
this.remarks,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id??0,
|
||||
'assetId': device?.id,
|
||||
'auditorId': auditorId,
|
||||
'findings': findings.map((e) => {'findingId': e.value}).toList(),
|
||||
'attachments': attachments.map((e) => e.toJson()).toList(),
|
||||
'remarks': remarks,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
import 'dart:developer';
|
||||
|
||||
class InternalAuditAttachments {
|
||||
InternalAuditAttachments({this.id, this.originalName, this.name, this.createdBy});
|
||||
|
||||
int? id;
|
||||
String? name;
|
||||
String? originalName;
|
||||
String? createdBy;
|
||||
|
||||
InternalAuditAttachments.fromJson(Map<String, dynamic> json) {
|
||||
log('name is ${json['name']}');
|
||||
id = json['id'];
|
||||
name = (json['name'] != null && !json['name'].toString().startsWith('data:image/jpeg')) ? json['name'] : null;
|
||||
originalName = json['originalName'];
|
||||
createdBy = json['createdBy'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['name'] = name;
|
||||
data['originalName'] = originalName;
|
||||
// data['createdBy'] = createdBy;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:test_sa/controllers/api_routes/urls.dart';
|
||||
import 'package:test_sa/extensions/context_extension.dart';
|
||||
import 'package:test_sa/models/device/asset.dart';
|
||||
import 'package:test_sa/models/fault_description.dart';
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
|
||||
class InternalAuditModel {
|
||||
String? id;
|
||||
int? deviceId;
|
||||
String? deviceArName;
|
||||
String? woOrderNo;
|
||||
List<String>? devicePhotos;
|
||||
Lookup? auditCheckList;
|
||||
String? comments;
|
||||
Asset? device;
|
||||
|
||||
InternalAuditModel({
|
||||
this.id,
|
||||
this.deviceArName,
|
||||
this.devicePhotos,
|
||||
this.deviceId,
|
||||
this.woOrderNo,
|
||||
this.comments,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
class InternalAuditTimerModel {
|
||||
int? id;
|
||||
String? startDate;
|
||||
String? endDate;
|
||||
double? totalWorkingHour;
|
||||
String? comment;
|
||||
|
||||
InternalAuditTimerModel({
|
||||
this.id,
|
||||
this.startDate,
|
||||
this.endDate,
|
||||
this.totalWorkingHour,
|
||||
this.comment,
|
||||
});
|
||||
|
||||
factory InternalAuditTimerModel.fromJson(Map<String, dynamic> json) {
|
||||
return InternalAuditTimerModel(
|
||||
id: json['id'] as int?,
|
||||
startDate: json['startDate'],
|
||||
endDate: json['endDate'],
|
||||
totalWorkingHour: (json['totalWorkingHours'] as num?)?.toDouble(),
|
||||
comment: json['comment'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'startDate': startDate,
|
||||
'endDate': endDate,
|
||||
'totalWorkingHours': totalWorkingHour,
|
||||
'comment': comment,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,138 @@
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/engineer_data_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/system_internal_audit_form_model.dart';
|
||||
|
||||
class SystemInternalAuditDataModel {
|
||||
int? id;
|
||||
int? assetGroupId;
|
||||
String? requestNo;
|
||||
int? requestNoSequence;
|
||||
Auditor? auditor;
|
||||
Lookup? status;
|
||||
Lookup? findingType;
|
||||
String? findingDescription;
|
||||
Lookup? workOrderType;
|
||||
Auditor? assignEmployee;
|
||||
SystemAuditWorkOrderDetailModel? workOrderDetails; // Already exists as a separate model
|
||||
String? createdBy;
|
||||
String? createdDate;
|
||||
String? modifiedBy;
|
||||
String? modifiedDate;
|
||||
List<InternalAuditAttachments>? attachments;
|
||||
EngineerData? engineerData;
|
||||
|
||||
SystemInternalAuditDataModel({
|
||||
this.id,
|
||||
this.assetGroupId,
|
||||
this.requestNo,
|
||||
this.requestNoSequence,
|
||||
this.auditor,
|
||||
this.status,
|
||||
this.findingType,
|
||||
this.findingDescription,
|
||||
this.workOrderType,
|
||||
this.assignEmployee,
|
||||
this.workOrderDetails,
|
||||
this.createdBy,
|
||||
this.createdDate,
|
||||
this.modifiedBy,
|
||||
this.modifiedDate,
|
||||
this.attachments,
|
||||
this.engineerData,
|
||||
});
|
||||
|
||||
SystemInternalAuditDataModel.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
assetGroupId = json['assetGroupId'];
|
||||
requestNo = json['requestNo'];
|
||||
requestNoSequence = json['requestNoSequence'];
|
||||
auditor = json['auditor'] != null ? Auditor.fromJson(json['auditor']) : null;
|
||||
status = json['status'] != null ? Lookup.fromJson(json['status']) : null;
|
||||
findingType = json['findingType'] != null ? Lookup.fromJson(json['findingType']) : null;
|
||||
findingDescription = json['findingDescription'];
|
||||
workOrderType = json['workOrderType'] != null ? Lookup.fromJson(json['workOrderType']) : null;
|
||||
assignEmployee = json['assignEmployee'] != null ? Auditor.fromJson(json['assignEmployee']) : null;
|
||||
workOrderDetails = json['workOrderDetails'] != null ? SystemAuditWorkOrderDetailModel.fromJson(json['workOrderDetails']) : null; // Keep as-is
|
||||
createdBy = json['createdBy'];
|
||||
createdDate = json['createdDate'];
|
||||
modifiedBy = json['modifiedBy'];
|
||||
modifiedDate = json['modifiedDate'];
|
||||
attachments = json['attachments'] != null
|
||||
? (json['attachments'] as List)
|
||||
.map((e) => InternalAuditAttachments.fromJson(e))
|
||||
.where((e) => e.name != null) // optional filter if you want to skip null names
|
||||
.toList()
|
||||
: [];
|
||||
engineerData = json['engineerData'] != null ? EngineerData.fromJson(json['engineerData']) : null;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = {};
|
||||
data['id'] = id;
|
||||
data['assetGroupId'] = assetGroupId;
|
||||
data['requestNo'] = requestNo;
|
||||
data['requestNoSequence'] = requestNoSequence;
|
||||
if (auditor != null) data['auditor'] = auditor!.toJson();
|
||||
if (status != null) data['status'] = status!.toJson();
|
||||
if (findingType != null) data['findingType'] = findingType!.toJson();
|
||||
data['findingDescription'] = findingDescription;
|
||||
if (workOrderType != null) data['workOrderType'] = workOrderType!.toJson();
|
||||
if (assignEmployee != null) data['assignEmployee'] = assignEmployee!.toJson();
|
||||
data['workOrderDetails'] = workOrderDetails;
|
||||
data['createdBy'] = createdBy;
|
||||
data['createdDate'] = createdDate;
|
||||
data['modifiedBy'] = modifiedBy;
|
||||
data['modifiedDate'] = modifiedDate;
|
||||
if (engineerData != null) data['engineerData'] = engineerData!.toJson();
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Auditor {
|
||||
String? userId;
|
||||
String? userName;
|
||||
String? email;
|
||||
String? employeeId;
|
||||
int? languageId;
|
||||
String? extensionNo;
|
||||
String? phoneNumber;
|
||||
bool? isActive;
|
||||
|
||||
Auditor({
|
||||
this.userId,
|
||||
this.userName,
|
||||
this.email,
|
||||
this.employeeId,
|
||||
this.languageId,
|
||||
this.extensionNo,
|
||||
this.phoneNumber,
|
||||
this.isActive,
|
||||
});
|
||||
|
||||
Auditor.fromJson(Map<String, dynamic> json) {
|
||||
userId = json['userId'];
|
||||
userName = json['userName'];
|
||||
email = json['email'];
|
||||
employeeId = json['employeeId'];
|
||||
languageId = json['languageId'];
|
||||
extensionNo = json['extensionNo'];
|
||||
phoneNumber = json['phoneNumber'];
|
||||
isActive = json['isActive'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = {};
|
||||
data['userId'] = userId;
|
||||
data['userName'] = userName;
|
||||
data['email'] = email;
|
||||
data['employeeId'] = employeeId;
|
||||
data['languageId'] = languageId;
|
||||
data['extensionNo'] = extensionNo;
|
||||
data['phoneNumber'] = phoneNumber;
|
||||
data['isActive'] = isActive;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,202 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
|
||||
|
||||
class SystemInternalAuditFormModel {
|
||||
int? id;
|
||||
String? auditorId;
|
||||
String? assignEmployeeId;
|
||||
Lookup? findingType;
|
||||
String? findingDescription;
|
||||
Lookup? workOrderType;
|
||||
int? correctiveMaintenanceId;
|
||||
int? planPreventiveVisitId;
|
||||
int? assetTransferId;
|
||||
List<InternalAuditAttachments>? attachments = [];
|
||||
int? taskJobId;
|
||||
int? taskAlertJobId;
|
||||
int? gasRefillId;
|
||||
int? planRecurrentTaskId;
|
||||
int? statusId;
|
||||
SystemAuditWorkOrderDetailModel? workOrderDetailModel;
|
||||
|
||||
SystemInternalAuditFormModel({
|
||||
this.id,
|
||||
this.auditorId,
|
||||
this.assignEmployeeId,
|
||||
this.findingType,
|
||||
this.findingDescription,
|
||||
this.workOrderType,
|
||||
this.correctiveMaintenanceId,
|
||||
this.planPreventiveVisitId,
|
||||
this.assetTransferId,
|
||||
this.taskJobId,
|
||||
this.taskAlertJobId,
|
||||
this.gasRefillId,
|
||||
this.planRecurrentTaskId,
|
||||
this.workOrderDetailModel,
|
||||
this.statusId,
|
||||
this.attachments,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
// 'id': id,
|
||||
'auditorId': auditorId,
|
||||
'assignEmployeeId': assignEmployeeId,
|
||||
'findingTypeId': findingType?.id,
|
||||
'findingDescription': findingDescription,
|
||||
'workOrderTypeId': workOrderType?.id,
|
||||
'correctiveMaintenanceId': correctiveMaintenanceId,
|
||||
'planPreventiveVisitId': planPreventiveVisitId,
|
||||
'assetTransferId': assetTransferId,
|
||||
'taskJobId': taskJobId,
|
||||
'taskAlertJobId': taskAlertJobId,
|
||||
'gasRefillId': gasRefillId,
|
||||
'planRecurrentTaskId': planRecurrentTaskId,
|
||||
'statusId': statusId,
|
||||
'attachments': attachments?.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class WoAutoCompleteModel {
|
||||
int? id;
|
||||
String? workOrderNo;
|
||||
String? displayName;
|
||||
|
||||
WoAutoCompleteModel({this.id, this.workOrderNo, this.displayName});
|
||||
|
||||
WoAutoCompleteModel.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
workOrderNo = json['workOrderNo'];
|
||||
displayName = json['workOrderNo'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['woOrderNo'] = workOrderNo;
|
||||
data['displayName'] = workOrderNo;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class SystemAuditWorkOrderDetailModel {
|
||||
String? createdBy;
|
||||
DateTime? createdDate;
|
||||
String? modifiedBy;
|
||||
DateTime? modifiedDate;
|
||||
int? id;
|
||||
String? workOrderNo;
|
||||
String? woAssignedEngineer;
|
||||
String? woAssetNo;
|
||||
String? wosn;
|
||||
String? woAssetName;
|
||||
String? woModel;
|
||||
String? woManufacturer;
|
||||
String? woSite;
|
||||
String? woDepartment;
|
||||
String? wOPMScheduleDate;
|
||||
String? wOPMActualVisitDate;
|
||||
String? wOAssetTransferDestinationSite;
|
||||
String? wOAssetTransferSenderEngineer;
|
||||
String? wOAssetTransferReceiverEngineer;
|
||||
String? wOTaskAlertJobImpactedStatus;
|
||||
String? wOTaskAlertJobAcknowledgment;
|
||||
String? wOGasRefillType;
|
||||
String? wORecurrentTaskTaskType;
|
||||
String? wORecurrentTaskPlanNo;
|
||||
String? wORecurrentTaskPlanName;
|
||||
String? wORecurrentTaskStatus;
|
||||
|
||||
SystemAuditWorkOrderDetailModel({
|
||||
this.createdBy,
|
||||
this.createdDate,
|
||||
this.modifiedBy,
|
||||
this.modifiedDate,
|
||||
this.id,
|
||||
this.workOrderNo,
|
||||
this.woAssignedEngineer,
|
||||
this.woAssetNo,
|
||||
this.wosn,
|
||||
this.woAssetName,
|
||||
this.woModel,
|
||||
this.woManufacturer,
|
||||
this.woSite,
|
||||
this.woDepartment,
|
||||
this.wOPMScheduleDate,
|
||||
this.wOPMActualVisitDate,
|
||||
this.wOAssetTransferDestinationSite,
|
||||
this.wOAssetTransferSenderEngineer,
|
||||
this.wOAssetTransferReceiverEngineer,
|
||||
this.wOTaskAlertJobImpactedStatus,
|
||||
this.wOTaskAlertJobAcknowledgment,
|
||||
this.wOGasRefillType,
|
||||
this.wORecurrentTaskTaskType,
|
||||
this.wORecurrentTaskPlanNo,
|
||||
this.wORecurrentTaskPlanName,
|
||||
this.wORecurrentTaskStatus,
|
||||
});
|
||||
|
||||
SystemAuditWorkOrderDetailModel.fromJson(Map<String, dynamic> json) {
|
||||
createdBy = json['createdBy'];
|
||||
createdDate = json['createdDate'] != null ? DateTime.tryParse(json['createdDate']) : null;
|
||||
modifiedBy = json['modifiedBy'];
|
||||
modifiedDate = json['modifiedDate'] != null ? DateTime.tryParse(json['modifiedDate']) : null;
|
||||
id = json['id'];
|
||||
workOrderNo = json['workOrderNo'];
|
||||
woAssignedEngineer = json['woAssignedEngineer'];
|
||||
woAssetNo = json['woAssetNo'];
|
||||
wosn = json['wosn'];
|
||||
woAssetName = json['woAssetName'];
|
||||
woModel = json['woModel'];
|
||||
woManufacturer = json['woManufacturer'];
|
||||
woSite = json['woSite'];
|
||||
woDepartment = json['woDepartment'];
|
||||
wOPMScheduleDate = json['wO_PM_ScheduleDate'];
|
||||
wOPMActualVisitDate = json['wO_PM_ActualVisitDate'];
|
||||
wOAssetTransferDestinationSite = json['wO_AssetTransfer_DestinationSite'];
|
||||
wOAssetTransferSenderEngineer = json['wO_AssetTransfer_SenderEngineer'];
|
||||
wOAssetTransferReceiverEngineer = json['wO_AssetTransfer_ReceiverEngineer'];
|
||||
wOTaskAlertJobImpactedStatus = json['wO_TaskAlertJob_ImpactedStatus'];
|
||||
wOTaskAlertJobAcknowledgment = json['wO_TaskAlertJob_Acknowledgment'];
|
||||
wOGasRefillType = json['wO_GasRefill_Type'];
|
||||
wORecurrentTaskTaskType = json['wO_RecurrentTask_TaskType'];
|
||||
wORecurrentTaskPlanNo = json['wO_RecurrentTask_PlanNo'];
|
||||
wORecurrentTaskPlanName = json['wO_RecurrentTask_PlanName'];
|
||||
wORecurrentTaskStatus = json['wO_RecurrentTask_Status'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'createdBy': createdBy,
|
||||
'createdDate': createdDate?.toIso8601String(),
|
||||
'modifiedBy': modifiedBy,
|
||||
'modifiedDate': modifiedDate?.toIso8601String(),
|
||||
'id': id,
|
||||
'workOrderNo': workOrderNo,
|
||||
'woAssignedEngineer': woAssignedEngineer,
|
||||
'woAssetNo': woAssetNo,
|
||||
'wosn': wosn,
|
||||
'woAssetName': woAssetName,
|
||||
'woModel': woModel,
|
||||
'woManufacturer': woManufacturer,
|
||||
'woSite': woSite,
|
||||
'woDepartment': woDepartment,
|
||||
'wO_PM_ScheduleDate': wOPMScheduleDate,
|
||||
'wO_PM_ActualVisitDate': wOPMActualVisitDate,
|
||||
'wO_AssetTransfer_DestinationSite': wOAssetTransferDestinationSite,
|
||||
'wO_AssetTransfer_SenderEngineer': wOAssetTransferSenderEngineer,
|
||||
'wO_AssetTransfer_ReceiverEngineer': wOAssetTransferReceiverEngineer,
|
||||
'wO_TaskAlertJob_ImpactedStatus': wOTaskAlertJobImpactedStatus,
|
||||
'wO_TaskAlertJob_Acknowledgment': wOTaskAlertJobAcknowledgment,
|
||||
'wO_GasRefill_Type': wOGasRefillType,
|
||||
'wO_RecurrentTask_TaskType': wORecurrentTaskTaskType,
|
||||
'wO_RecurrentTask_PlanNo': wORecurrentTaskPlanNo,
|
||||
'wO_RecurrentTask_PlanName': wORecurrentTaskPlanName,
|
||||
'wO_RecurrentTask_Status': wORecurrentTaskStatus,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
import 'package:test_sa/models/timer_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_timer_model.dart';
|
||||
|
||||
class AuditFormModel {
|
||||
int? id;
|
||||
String? createdDate;
|
||||
int? requestId;
|
||||
String? debrief;
|
||||
DateTime? startTime;
|
||||
DateTime? endTime;
|
||||
double? totalHours;
|
||||
List<InternalAuditAttachments>? attachments;
|
||||
bool? isComplete;
|
||||
TimerModel? auditTimerModel = TimerModel();
|
||||
List<InternalAuditTimerModel>? auditTimers = [];
|
||||
TimerModel? auditTimePicker;
|
||||
List<TimerModel>? timerModelList = [];
|
||||
|
||||
AuditFormModel(
|
||||
{this.id,
|
||||
this.requestId,
|
||||
this.debrief,
|
||||
this.startTime,
|
||||
this.endTime,
|
||||
this.totalHours,
|
||||
this.createdDate,
|
||||
this.attachments,
|
||||
this.isComplete,
|
||||
this.auditTimerModel,
|
||||
this.timerModelList,
|
||||
this.auditTimePicker,
|
||||
this.auditTimers});
|
||||
|
||||
AuditFormModel.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
requestId = json['requestId'];
|
||||
debrief = json['debrief'];
|
||||
startTime = json['startTime'] != null ? DateTime.tryParse(json['startTime']) : null;
|
||||
endTime = json['endTime'] != null ? DateTime.tryParse(json['endTime']) : null;
|
||||
totalHours = json['totalHours']?.toDouble();
|
||||
if (json['attachments'] != null) {
|
||||
attachments = (json['attachments'] as List).map((e) => InternalAuditAttachments.fromJson(e)).toList();
|
||||
}
|
||||
isComplete = json['isComplete'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'requestId': requestId,
|
||||
'debrief': debrief,
|
||||
'startTime': startTime?.toIso8601String(),
|
||||
'endTime': endTime?.toIso8601String(),
|
||||
// 'auditTimer': auditTimers,
|
||||
'totalHours': totalHours,
|
||||
'attachments': attachments?.map((e) => e.toJson()).toList(),
|
||||
'isComplete': isComplete,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,321 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/api_routes/api_manager.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/generic_attachment_model.dart';
|
||||
import 'package:test_sa/models/timer_model.dart';
|
||||
import 'package:test_sa/modules/cm_module/utilities/service_request_utils.dart';
|
||||
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_timer_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/update_audit_form_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/equipment_internal_audit_data_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_provider.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/app_lazy_loading.dart';
|
||||
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
|
||||
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
|
||||
import 'package:test_sa/new_views/common_widgets/working_time_tile.dart';
|
||||
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
|
||||
import 'package:test_sa/views/widgets/timer/app_timer.dart';
|
||||
import 'package:test_sa/views/widgets/total_working_time_detail_bottomsheet.dart';
|
||||
|
||||
class UpdateEquipmentInternalAuditPage extends StatefulWidget {
|
||||
static const String id = "update-equipment-internal-audit";
|
||||
EquipmentInternalAuditDataModel? model;
|
||||
|
||||
UpdateEquipmentInternalAuditPage({Key? key, this.model}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<UpdateEquipmentInternalAuditPage> createState() => _UpdateEquipmentInternalAuditPageState();
|
||||
}
|
||||
|
||||
class _UpdateEquipmentInternalAuditPageState extends State<UpdateEquipmentInternalAuditPage> {
|
||||
final bool _isLoading = false;
|
||||
double totalWorkingHours = 0.0;
|
||||
AuditFormModel formModel = AuditFormModel();
|
||||
final TextEditingController _workingHoursController = TextEditingController();
|
||||
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
List<GenericAttachmentModel> _attachments = [];
|
||||
|
||||
//TODO need to check if it's needed or not..
|
||||
List<TimerHistoryModel> timerList = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
populateForm();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void populateForm() {
|
||||
formModel.requestId = widget.model?.id;
|
||||
formModel.id = widget.model?.id;
|
||||
_attachments = widget.model?.engineerData?.attachments?.map((e) => GenericAttachmentModel(id: e.id?.toInt() ?? 0, name: e.name!)).toList() ?? [];
|
||||
|
||||
calculateWorkingTime();
|
||||
}
|
||||
|
||||
void calculateWorkingTime() {
|
||||
final helperModel = formModel;
|
||||
final timers = helperModel.auditTimers ?? [];
|
||||
totalWorkingHours = timers.fold<double>(0.0, (sum, item) {
|
||||
if (item.startDate == null || item.endDate == null) return sum;
|
||||
try {
|
||||
final start = DateTime.parse(item.startDate!);
|
||||
final end = DateTime.parse(item.endDate!);
|
||||
final diffInHours = end.difference(start).inSeconds / 3600.0; // convert to hours
|
||||
return sum + diffInHours;
|
||||
} catch (_) {
|
||||
return sum;
|
||||
}
|
||||
});
|
||||
timerList = timers.map((e) {
|
||||
return TimerHistoryModel(
|
||||
id: e.id,
|
||||
startTime: e.startDate,
|
||||
endTime: e.endDate,
|
||||
workingHours: e.startDate,
|
||||
);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
_onSubmit(BuildContext context) async {
|
||||
bool isTimerPickerEnable = ApiManager.instance.assetGroup?.enabledEngineerTimer ?? false;
|
||||
InternalAuditProvider provider = Provider.of<InternalAuditProvider>(context, listen: false);
|
||||
|
||||
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
|
||||
formModel.auditTimers ??= [];
|
||||
if (formModel.auditTimePicker != null) {
|
||||
int durationInSecond = formModel.auditTimePicker!.endAt!.difference(formModel.auditTimePicker!.startAt!).inSeconds;
|
||||
formModel.auditTimers?.add(
|
||||
InternalAuditTimerModel(
|
||||
id: 0,
|
||||
startDate: formModel.auditTimePicker!.startAt!.toIso8601String(), // Handle potential null
|
||||
endDate: formModel.auditTimePicker!.endAt?.toIso8601String(), // Handle potential null
|
||||
totalWorkingHour: ((durationInSecond) / 60 / 60),
|
||||
),
|
||||
);
|
||||
}
|
||||
formModel.timerModelList?.forEach((timer) {
|
||||
int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds;
|
||||
formModel.auditTimers?.add(
|
||||
InternalAuditTimerModel(
|
||||
id: 0,
|
||||
startDate: timer.startAt!.toIso8601String(), // Handle potential null
|
||||
endDate: timer.endAt?.toIso8601String(), // Handle potential null
|
||||
totalWorkingHour: ((durationInSecond) / 60 / 60),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
_formKey.currentState!.save();
|
||||
formModel.attachments = [];
|
||||
for (var item in _attachments) {
|
||||
String fileName = ServiceRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name?.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
|
||||
formModel.attachments!.add(
|
||||
InternalAuditAttachments(
|
||||
id: item.id,
|
||||
originalName: fileName,
|
||||
name: fileName,
|
||||
),
|
||||
);
|
||||
}
|
||||
final success = await provider.updateEquipmentInternalAudit(model: formModel);
|
||||
Navigator.pop(context);
|
||||
if (formModel.isComplete == true) {
|
||||
//Navigate to List screen.
|
||||
} else if (formModel.isComplete == false) {
|
||||
//Navigate to Detail screen.
|
||||
if (success) {
|
||||
Navigator.of(context).pop(true);
|
||||
} else {
|
||||
Fluttertoast.showToast(msg: 'Failed to update');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_workingHoursController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void updateTimer({TimerModel? timer}) {
|
||||
if (timer?.startAt != null && timer?.endAt != null) {
|
||||
final start = timer!.startAt!;
|
||||
final end = timer.endAt!;
|
||||
|
||||
final difference = end.difference(start);
|
||||
final totalHours = difference.inSeconds / 3600.0;
|
||||
formModel.startTime = start;
|
||||
formModel.endTime = end;
|
||||
formModel.totalHours = totalHours;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: DefaultAppBar(
|
||||
title: 'Update Information'.addTranslation,
|
||||
onWillPopScope: () {
|
||||
formModel.isComplete = false;
|
||||
_onSubmit(context);
|
||||
},
|
||||
),
|
||||
key: _scaffoldKey,
|
||||
body: Form(
|
||||
key: _formKey,
|
||||
child: LoadingManager(
|
||||
isLoading: _isLoading,
|
||||
isFailedLoading: false,
|
||||
stateCode: 200,
|
||||
onRefresh: () async {},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
8.height,
|
||||
AppTextFormField(
|
||||
labelText: 'Debrief'.addTranslation,
|
||||
textInputType: TextInputType.multiline,
|
||||
hintStyle: TextStyle(color: context.isDark ? AppColor.white10 : AppColor.black10),
|
||||
labelStyle: TextStyle(color: context.isDark ? AppColor.white10 : AppColor.black10),
|
||||
alignLabelWithHint: true,
|
||||
initialValue: formModel.debrief,
|
||||
backgroundColor: AppColor.fieldBgColor(context),
|
||||
showShadow: false,
|
||||
onSaved: (value) {
|
||||
formModel.debrief = value;
|
||||
},
|
||||
),
|
||||
8.height,
|
||||
_timerWidget(context, totalWorkingHours),
|
||||
16.height,
|
||||
AttachmentPicker(
|
||||
label: 'Upload Attachment',
|
||||
attachment: _attachments,
|
||||
buttonColor: AppColor.primary10,
|
||||
onlyImages: false,
|
||||
buttonIcon: 'attachment_icon'.toSvgAsset(
|
||||
color: AppColor.primary10,
|
||||
),
|
||||
),
|
||||
8.height,
|
||||
],
|
||||
).toShadowContainer(context),
|
||||
).expanded,
|
||||
FooterActionButton.footerContainer(
|
||||
context: context,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
AppFilledButton(
|
||||
label: context.translation.save,
|
||||
buttonColor: context.isDark ? AppColor.neutral70 : AppColor.white60,
|
||||
textColor: context.isDark ? AppColor.white10 : AppColor.black10,
|
||||
onPressed: () {
|
||||
formModel.isComplete = false;
|
||||
_onSubmit(context);
|
||||
}).expanded,
|
||||
12.width,
|
||||
AppFilledButton(
|
||||
label: context.translation.complete,
|
||||
buttonColor: AppColor.primary10,
|
||||
onPressed: () {
|
||||
formModel.isComplete = true;
|
||||
_onSubmit(context);
|
||||
}).expanded,
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)),
|
||||
),
|
||||
).handlePopScope(
|
||||
cxt: context,
|
||||
onSave: () {
|
||||
formModel.isComplete = false;
|
||||
_onSubmit(context);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _timerWidget(BuildContext context, double totalWorkingHours) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
//TODO multiple timer ..
|
||||
// AppTimer(
|
||||
// label: context.translation.timer,
|
||||
// timer: formModel.auditTimerModel,
|
||||
// // enabled: enableTimer,
|
||||
// pickerTimer: formModel.auditTimePicker,
|
||||
// pickerFromDate: DateTime.tryParse(widget.model?.createdDate ?? ''),
|
||||
// onPick: (time) {
|
||||
// formModel.auditTimePicker = time;
|
||||
// setState(() {});
|
||||
// log('Time picker start ${formModel.auditTimePicker?.startAt}');
|
||||
// log('Time picker end ${formModel.auditTimePicker?.endAt}');
|
||||
// },
|
||||
// timerProgress: (isRunning) {},
|
||||
// onChange: (timer) async {
|
||||
// formModel.auditTimerModel = timer;
|
||||
// log('start ${formModel.auditTimerModel?.startAt}');
|
||||
// log('end ${formModel.auditTimerModel?.endAt}');
|
||||
// if (timer.startAt != null && timer.endAt != null) {
|
||||
// formModel.timerModelList = formModel.timerModelList ?? [];
|
||||
// formModel.timerModelList!.add(timer);
|
||||
// }
|
||||
// setState(() {});
|
||||
// log('list length ${formModel.timerModelList?.length}');
|
||||
// return true;
|
||||
// },
|
||||
// ),
|
||||
AppTimer(
|
||||
label: context.translation.workingHours,
|
||||
timer: formModel.auditTimerModel,
|
||||
pickerFromDate: DateTime.tryParse(widget.model?.createdDate ?? ''),
|
||||
pickerTimer: formModel.auditTimePicker,
|
||||
onPick: (timer) {
|
||||
updateTimer(timer: timer);
|
||||
},
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.fieldBgColor(context),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
timerProgress: (isRunning) {},
|
||||
onChange: (timer) async {
|
||||
updateTimer(timer: timer);
|
||||
log('here onChange ${timer.startAt}');
|
||||
|
||||
return true;
|
||||
},
|
||||
),
|
||||
if (totalWorkingHours > 0.0) ...[
|
||||
12.height,
|
||||
WorkingTimeTile(
|
||||
timerList: timerList,
|
||||
totalWorkingTime: totalWorkingHours,
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,149 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/api_routes/urls.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/modules/internal_audit_module/models/system_internal_audit_form_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_provider.dart';
|
||||
import 'package:test_sa/new_views/app_style/app_color.dart';
|
||||
import 'package:test_sa/new_views/app_style/app_text_style.dart';
|
||||
import 'package:test_sa/views/app_style/sizing.dart';
|
||||
|
||||
class SystemAuditWoAutoCompleteField extends StatefulWidget {
|
||||
final String initialValue;
|
||||
final int? woTypeId;
|
||||
final TextEditingController controller;
|
||||
final bool clearAfterPick;
|
||||
final Function(WoAutoCompleteModel) onPick;
|
||||
|
||||
const SystemAuditWoAutoCompleteField({Key? key, required this.initialValue, this.woTypeId, required this.onPick, this.clearAfterPick = true, required this.controller}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SystemAuditWoAutoCompleteFieldState createState() => _SystemAuditWoAutoCompleteFieldState();
|
||||
}
|
||||
|
||||
class _SystemAuditWoAutoCompleteFieldState extends State<SystemAuditWoAutoCompleteField> {
|
||||
late InternalAuditProvider _provider;
|
||||
|
||||
//
|
||||
// late TextEditingController _controller;
|
||||
|
||||
bool loading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// w controller = widget.controller ?? TextEditingController(text: widget.initialValue);
|
||||
super.initState();
|
||||
_provider = Provider.of<InternalAuditProvider>(context, listen: false);
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant SystemAuditWoAutoCompleteField oldWidget) {
|
||||
// if (widget.initialValue != oldWidget.initialValue) {
|
||||
// // _controller = widget.controller ?? TextEditingController(text: widget.initialValue);
|
||||
// }
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
if (widget.controller == null) {
|
||||
// _controller.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final border = UnderlineInputBorder(borderSide: BorderSide.none, borderRadius: BorderRadius.circular(10));
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.background(context),
|
||||
borderRadius: BorderRadius.circular(AppStyle.borderRadius * AppStyle.getScaleFactor(context)),
|
||||
// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
|
||||
),
|
||||
child: Autocomplete<WoAutoCompleteModel>(
|
||||
optionsBuilder: (TextEditingValue textEditingValue) async {
|
||||
if (textEditingValue.text.isEmpty) {
|
||||
if (loading) {
|
||||
setState(() {
|
||||
loading = false;
|
||||
});
|
||||
}
|
||||
return const Iterable<WoAutoCompleteModel>.empty();
|
||||
}
|
||||
if (!loading) {
|
||||
setState(() {
|
||||
loading = true;
|
||||
});
|
||||
}
|
||||
List<WoAutoCompleteModel> workOrders = (await _provider.getWorkOrderByWoType(text: textEditingValue.text, woId:widget.woTypeId));
|
||||
setState(() {
|
||||
loading = false;
|
||||
});
|
||||
return workOrders;
|
||||
},
|
||||
displayStringForOption: (WoAutoCompleteModel option) => option.displayName ?? '',
|
||||
fieldViewBuilder: (BuildContext context, TextEditingController fieldTextEditingController, FocusNode fieldFocusNode, VoidCallback onFieldSubmitted) {
|
||||
return TextField(
|
||||
controller: widget.controller,
|
||||
focusNode: fieldFocusNode,
|
||||
style: AppTextStyles.bodyText.copyWith(color: AppColor.black10),
|
||||
textAlign: TextAlign.start,
|
||||
decoration: InputDecoration(
|
||||
border: border,
|
||||
disabledBorder: border,
|
||||
focusedBorder: border,
|
||||
enabledBorder: border,
|
||||
errorBorder: border,
|
||||
contentPadding: EdgeInsets.symmetric(vertical: 8.toScreenHeight, horizontal: 16.toScreenWidth),
|
||||
constraints: const BoxConstraints(),
|
||||
suffixIconConstraints: const BoxConstraints(maxHeight: 24, maxWidth: 24 + 8),
|
||||
filled: true,
|
||||
fillColor: AppColor.fieldBgColor(context),
|
||||
errorStyle: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red60),
|
||||
floatingLabelStyle: AppTextStyle.body1.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? null : AppColor.neutral20),
|
||||
labelText: context.translation.woNumber,
|
||||
labelStyle: AppTextStyles.tinyFont.copyWith(color: AppColor.textColor(context)),
|
||||
suffixIcon: loading ? const CircularProgressIndicator(color: AppColor.primary10, strokeWidth: 3.0).paddingOnly(end: 8) : null,
|
||||
),
|
||||
textInputAction: TextInputAction.search,
|
||||
onChanged: (text) {
|
||||
fieldTextEditingController.text = text;
|
||||
},
|
||||
onSubmitted: (String value) {
|
||||
onFieldSubmitted();
|
||||
},
|
||||
);
|
||||
},
|
||||
onSelected: (WoAutoCompleteModel selection) {
|
||||
if (widget.clearAfterPick) {
|
||||
widget.controller.clear();
|
||||
} else {
|
||||
widget.controller.text = (selection.displayName ?? "");
|
||||
}
|
||||
widget.onPick(selection);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// String getUrl(int? woTypeId) {
|
||||
// if (woTypeId == null) return '';
|
||||
// String base = URLs.woAutoCompleteBase;
|
||||
// var urlMap = {
|
||||
// 1: '$base/ServiceRequest/WorkOrderAutoComplete', // CM
|
||||
// 2: '$base/GasRefill/GetGasRefillAutoComplete', // Gas Refill
|
||||
// 3: '$base/AssetTransfer/GetAssetTransferAutoComplete', // Asset Transfer
|
||||
// 4: '$base/PlanPreventiveVisit/GetAutoCompletePlanPreventiveVisit', // PPM Request
|
||||
// 5: '$base/PlanRecurrentTasks/GetPlanRecurrentTask', // Recurrent WO
|
||||
// 6: '$base/TaskJobs/AutocompleteTaskJob', // Task
|
||||
// 7: '$base/TaskJobs/AutocompleteTaskJob', // Recall & Alert
|
||||
// };
|
||||
// return urlMap[woTypeId] ?? '';
|
||||
// }
|
||||
}
|
||||
@ -0,0 +1,219 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/api_routes/urls.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/modules/cm_module/views/components/action_button/footer_action_button.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/system_internal_audit_data_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/pages/equipment_internal_audit/update_equipment_internal_audit_page.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/pages/system_internal_audit/update_system_internal_audit_page.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_provider.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 'package:test_sa/views/widgets/images/files_list.dart';
|
||||
|
||||
import 'package:test_sa/views/widgets/loaders/app_loading.dart';
|
||||
|
||||
class SystemInternalAuditDetailPage extends StatefulWidget {
|
||||
static const String id = "/details-system-internal-audit";
|
||||
final int auditId;
|
||||
|
||||
SystemInternalAuditDetailPage({Key? key, required this.auditId}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SystemInternalAuditDetailPageState createState() {
|
||||
return _SystemInternalAuditDetailPageState();
|
||||
}
|
||||
}
|
||||
|
||||
class _SystemInternalAuditDetailPageState extends State<SystemInternalAuditDetailPage> {
|
||||
bool isWoType = true;
|
||||
SystemInternalAuditDataModel? model;
|
||||
late InternalAuditProvider _internalAuditProvider;
|
||||
List<InternalAuditAttachments> allAttachments = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_internalAuditProvider = Provider.of<InternalAuditProvider>(context, listen: false);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
getAuditData();
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> getAuditData() async {
|
||||
model = await _internalAuditProvider.getInternalSystemAuditById(widget.auditId);
|
||||
allAttachments.clear();
|
||||
allAttachments = [
|
||||
...(model?.attachments ?? []),
|
||||
...(model?.engineerData?.attachments ?? []),
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
//TODO need to check when implementing provider needed or not .
|
||||
return Scaffold(
|
||||
appBar: const DefaultAppBar(title: "Request Details"),
|
||||
body: Selector<InternalAuditProvider, bool>(
|
||||
selector: (_, provider) => provider.isLoading,
|
||||
builder: (_, isLoading, __) {
|
||||
if (isLoading) return const ALoading();
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
assetInformation(),
|
||||
8.height,
|
||||
workOrderInformation(),
|
||||
8.height,
|
||||
//TODO need to check for comments
|
||||
if (model?.findingDescription?.isNotEmpty ?? false) ...[
|
||||
const Divider().defaultStyle(context),
|
||||
// Text(
|
||||
// "Comments".addTranslation,
|
||||
// style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||
// ),
|
||||
model!.findingDescription!.bodyText(context),
|
||||
],
|
||||
//TODO need to check for attachments
|
||||
if (allAttachments.isNotEmpty) ...[
|
||||
const Divider().defaultStyle(context),
|
||||
Text(
|
||||
"Attachments".addTranslation,
|
||||
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||
),
|
||||
8.height,
|
||||
FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
|
||||
],
|
||||
],
|
||||
).paddingAll(0).toShadowContainer(context),
|
||||
).expanded,
|
||||
if (context.userProvider.isEngineer)
|
||||
FooterActionButton.footerContainer(
|
||||
context: context,
|
||||
child: AppFilledButton(
|
||||
buttonColor: AppColor.primary10,
|
||||
label: "Update",
|
||||
onPressed: () async {
|
||||
final result = await Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (_) => UpdateSystemInternalAuditPage(model: model),
|
||||
),
|
||||
);
|
||||
if (result == true) {
|
||||
await getAuditData();
|
||||
setState(() {}); // refresh UI with new model
|
||||
}
|
||||
}),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
Widget workOrderInformation() {
|
||||
final details = model?.workOrderDetails;
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Divider().defaultStyle(context),
|
||||
Text(
|
||||
"WO Info",
|
||||
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||
),
|
||||
6.height,
|
||||
labelValueText(context, context.translation.woNumber, details?.workOrderNo),
|
||||
labelValueText(context, 'WO Type'.addTranslation, model?.workOrderType?.name),
|
||||
labelValueText(context, context.translation.site, details?.woSite),
|
||||
labelValueText(context, context.translation.assetName, details?.woAssetName),
|
||||
labelValueText(context, context.translation.manufacture, details?.woManufacturer),
|
||||
labelValueText(context, context.translation.model, details?.woModel),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget requestDetails() {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Divider().defaultStyle(context),
|
||||
Text(
|
||||
"Request Details",
|
||||
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||
),
|
||||
6.height,
|
||||
checklistWidget(value: 'Asset Tag'.addTranslation),
|
||||
checklistWidget(value: 'Expired PM Tag'.addTranslation),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget assetInformation() {
|
||||
final details = model?.workOrderDetails;
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Asset Details",
|
||||
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
|
||||
),
|
||||
6.height,
|
||||
labelValueText(context, context.translation.assetName, details?.woAssetName),
|
||||
labelValueText(context, context.translation.assetNo, details?.woAssetNo),
|
||||
labelValueText(context, context.translation.manufacture, details?.woManufacturer),
|
||||
labelValueText(context, context.translation.model, details?.woModel),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget labelValueText(BuildContext context, String label, String? value) {
|
||||
if (value == null || value.isEmpty) return const SizedBox.shrink();
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4),
|
||||
child: Text(
|
||||
'$label: $value',
|
||||
style: AppTextStyles.bodyText.copyWith(
|
||||
color: context.isDark ? AppColor.neutral30 : AppColor.neutral120,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget checklistWidget({required String value}) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Checkbox(
|
||||
value: true,
|
||||
activeColor: AppColor.neutral120,
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
visualDensity: const VisualDensity(horizontal: -4, vertical: -3),
|
||||
onChanged: (value) {},
|
||||
),
|
||||
value.bodyText(context),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.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/all_requests_and_count_model.dart';
|
||||
import 'package:test_sa/models/new_models/dashboard_detail.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/pages/equipment_internal_audit/equipment_internal_audit_detail_page.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/pages/system_internal_audit/system_internal_audit_detail_page.dart';
|
||||
import 'package:test_sa/new_views/app_style/app_color.dart';
|
||||
import 'package:test_sa/views/widgets/requests/request_status.dart';
|
||||
|
||||
class SystemInternalAuditItemView extends StatelessWidget {
|
||||
final Data? requestData;
|
||||
final RequestsDetails? requestDetails;
|
||||
final bool showShadow;
|
||||
|
||||
const SystemInternalAuditItemView({Key? key, this.requestData, this.requestDetails, this.showShadow = true}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
//TODO need to refactor this code repetation @waseem
|
||||
if (requestData != null) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
StatusLabel(
|
||||
label: requestData!.statusName!,
|
||||
textColor: AppColor.getRequestStatusTextColorByName(context, requestData!.statusName!),
|
||||
backgroundColor: AppColor.getRequestStatusColorByName(context, requestData!.statusName!),
|
||||
),
|
||||
1.width.expanded,
|
||||
Text(
|
||||
requestData!.transactionDate?.toServiceRequestCardFormat ?? "",
|
||||
textAlign: TextAlign.end,
|
||||
style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
|
||||
),
|
||||
],
|
||||
),
|
||||
8.height,
|
||||
(requestData?.typeTransaction ?? "Internal Audit Request").heading5(context),
|
||||
infoWidget(label: context.translation.assetNo, value: requestData?.assetNumber, context: context),
|
||||
|
||||
8.height,
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
context.translation.viewDetails,
|
||||
style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)),
|
||||
),
|
||||
4.width,
|
||||
Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14)
|
||||
],
|
||||
),
|
||||
],
|
||||
).toShadowContainer(context, withShadow: showShadow).onPress(() async {
|
||||
Navigator.push(context, MaterialPageRoute(builder: (context) => SystemInternalAuditDetailPage(auditId: requestDetails!.id!)));
|
||||
});
|
||||
}
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
StatusLabel(
|
||||
label: requestDetails!.status!,
|
||||
textColor: AppColor.getRequestStatusTextColorByName(context, requestDetails?.status!),
|
||||
backgroundColor: AppColor.getRequestStatusColorByName(context, requestDetails?.status!),
|
||||
),
|
||||
1.width.expanded,
|
||||
Text(
|
||||
requestDetails!.date?.toServiceRequestCardFormat ?? "",
|
||||
textAlign: TextAlign.end,
|
||||
style: AppTextStyles.tinyFont.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral50),
|
||||
),
|
||||
],
|
||||
),
|
||||
8.height,
|
||||
(requestDetails?.nameOfType ?? "Internal Audit Request").heading5(context),
|
||||
infoWidget(label: context.translation.assetNumber, value: requestDetails!.assetNo, context: context),
|
||||
infoWidget(label: context.translation.assetSN, value: requestDetails!.assetSN, context: context),
|
||||
infoWidget(label: context.translation.model, value: requestDetails!.model, context: context),
|
||||
8.height,
|
||||
// infoWidget(label: context.translation.site, value: requestDetails!.site, context: context),
|
||||
8.height,
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
context.translation.viewDetails,
|
||||
style: AppTextStyles.bodyText.copyWith(color: AppColor.blueStatus(context)),
|
||||
),
|
||||
4.width,
|
||||
Icon(Icons.arrow_forward, color: AppColor.blueStatus(context), size: 14)
|
||||
],
|
||||
),
|
||||
],
|
||||
).toShadowContainer(context, withShadow: showShadow).onPress(() async {
|
||||
Navigator.push(context, MaterialPageRoute(builder: (context) => SystemInternalAuditDetailPage(auditId: requestDetails!.id!)));
|
||||
});
|
||||
}
|
||||
|
||||
Widget infoWidget({required String label, String? value, required BuildContext context}) {
|
||||
if (value != null && value.isNotEmpty) {
|
||||
return '$label: $value'.bodyText(context);
|
||||
}
|
||||
return const SizedBox();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,314 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/api_routes/api_manager.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/generic_attachment_model.dart';
|
||||
import 'package:test_sa/models/timer_model.dart';
|
||||
import 'package:test_sa/modules/cm_module/utilities/service_request_utils.dart';
|
||||
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_timer_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/system_internal_audit_data_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/update_audit_form_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/models/internal_audit_attachment_model.dart';
|
||||
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_provider.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/app_lazy_loading.dart';
|
||||
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
|
||||
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
|
||||
import 'package:test_sa/new_views/common_widgets/working_time_tile.dart';
|
||||
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
|
||||
import 'package:test_sa/views/widgets/timer/app_timer.dart';
|
||||
import 'package:test_sa/views/widgets/total_working_time_detail_bottomsheet.dart';
|
||||
|
||||
class UpdateSystemInternalAuditPage extends StatefulWidget {
|
||||
static const String id = "update-system-internal-audit";
|
||||
SystemInternalAuditDataModel? model;
|
||||
|
||||
UpdateSystemInternalAuditPage({Key? key, this.model}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<UpdateSystemInternalAuditPage> createState() => _UpdateSystemInternalAuditPageState();
|
||||
}
|
||||
|
||||
class _UpdateSystemInternalAuditPageState extends State<UpdateSystemInternalAuditPage> {
|
||||
final bool _isLoading = false;
|
||||
double totalWorkingHours = 0.0;
|
||||
AuditFormModel formModel = AuditFormModel();
|
||||
final TextEditingController _workingHoursController = TextEditingController();
|
||||
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
List<GenericAttachmentModel> _attachments = [];
|
||||
|
||||
//TODO need to check if it's needed or not..
|
||||
List<TimerHistoryModel> timerList = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
populateForm();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void populateForm() {
|
||||
formModel.requestId = widget.model?.id;
|
||||
formModel.id = widget.model?.id;
|
||||
_attachments = widget.model?.engineerData?.attachments?.map((e) => GenericAttachmentModel(id: e.id?.toInt() ?? 0, name: e.name!)).toList() ?? [];
|
||||
|
||||
calculateWorkingTime();
|
||||
}
|
||||
|
||||
void calculateWorkingTime() {
|
||||
final helperModel = formModel;
|
||||
final timers = helperModel.auditTimers ?? [];
|
||||
totalWorkingHours = timers.fold<double>(0.0, (sum, item) {
|
||||
if (item.startDate == null || item.endDate == null) return sum;
|
||||
try {
|
||||
final start = DateTime.parse(item.startDate!);
|
||||
final end = DateTime.parse(item.endDate!);
|
||||
final diffInHours = end.difference(start).inSeconds / 3600.0; // convert to hours
|
||||
return sum + diffInHours;
|
||||
} catch (_) {
|
||||
return sum;
|
||||
}
|
||||
});
|
||||
timerList = timers.map((e) {
|
||||
return TimerHistoryModel(
|
||||
id: e.id,
|
||||
startTime: e.startDate,
|
||||
endTime: e.endDate,
|
||||
workingHours: e.startDate,
|
||||
);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
_onSubmit(BuildContext context) async {
|
||||
bool isTimerPickerEnable = ApiManager.instance.assetGroup?.enabledEngineerTimer ?? false;
|
||||
InternalAuditProvider provider = Provider.of<InternalAuditProvider>(context, listen: false);
|
||||
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
|
||||
|
||||
formModel.auditTimers ??= [];
|
||||
if (formModel.auditTimePicker != null) {
|
||||
int durationInSecond = formModel.auditTimePicker!.endAt!.difference(formModel.auditTimePicker!.startAt!).inSeconds;
|
||||
formModel.auditTimers?.add(
|
||||
InternalAuditTimerModel(
|
||||
id: 0,
|
||||
startDate: formModel.auditTimePicker!.startAt!.toIso8601String(), // Handle potential null
|
||||
endDate: formModel.auditTimePicker!.endAt?.toIso8601String(), // Handle potential null
|
||||
totalWorkingHour: ((durationInSecond) / 60 / 60),
|
||||
),
|
||||
);
|
||||
}
|
||||
formModel.timerModelList?.forEach((timer) {
|
||||
int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds;
|
||||
formModel.auditTimers?.add(
|
||||
InternalAuditTimerModel(
|
||||
id: 0,
|
||||
startDate: timer.startAt!.toIso8601String(), // Handle potential null
|
||||
endDate: timer.endAt?.toIso8601String(), // Handle potential null
|
||||
totalWorkingHour: ((durationInSecond) / 60 / 60),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
_formKey.currentState!.save();
|
||||
formModel.attachments = [];
|
||||
for (var item in _attachments) {
|
||||
String fileName = ServiceRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name?.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
|
||||
formModel.attachments!.add(
|
||||
InternalAuditAttachments(
|
||||
id: item.id,
|
||||
// originalName: fileName,
|
||||
name: fileName,
|
||||
),
|
||||
);
|
||||
}
|
||||
log('submit press');
|
||||
log('data ${formModel.toJson()}');
|
||||
final success = await provider.updateSystemInternalAudit(model: formModel);
|
||||
Navigator.pop(context);
|
||||
if (formModel.isComplete == true) {
|
||||
//Navigate to List screen.
|
||||
} else if (formModel.isComplete == false) {
|
||||
if (success) {
|
||||
Navigator.of(context).pop(true);
|
||||
} else {
|
||||
Fluttertoast.showToast(msg: 'Failed to update');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_workingHoursController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void updateTimer({TimerModel? timer}) {
|
||||
if (timer?.startAt != null && timer?.endAt != null) {
|
||||
final start = timer!.startAt!;
|
||||
final end = timer.endAt!;
|
||||
|
||||
final difference = end.difference(start);
|
||||
final totalHours = difference.inSeconds / 3600.0;
|
||||
formModel.startTime = start;
|
||||
formModel.endTime = end;
|
||||
formModel.totalHours = totalHours;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: DefaultAppBar(
|
||||
title: 'Update Information'.addTranslation,
|
||||
onWillPopScope: () {
|
||||
formModel.isComplete = false;
|
||||
_onSubmit(context);
|
||||
},
|
||||
),
|
||||
key: _scaffoldKey,
|
||||
body: Form(
|
||||
key: _formKey,
|
||||
child: LoadingManager(
|
||||
isLoading: _isLoading,
|
||||
isFailedLoading: false,
|
||||
stateCode: 200,
|
||||
onRefresh: () async {},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
8.height,
|
||||
AppTextFormField(
|
||||
labelText: 'Debrief'.addTranslation,
|
||||
textInputType: TextInputType.multiline,
|
||||
hintStyle: TextStyle(color: context.isDark ? AppColor.white10 : AppColor.black10),
|
||||
labelStyle: TextStyle(color: context.isDark ? AppColor.white10 : AppColor.black10),
|
||||
alignLabelWithHint: true,
|
||||
initialValue: formModel.debrief,
|
||||
backgroundColor: AppColor.fieldBgColor(context),
|
||||
showShadow: false,
|
||||
onSaved: (value) {
|
||||
formModel.debrief = value;
|
||||
},
|
||||
),
|
||||
8.height,
|
||||
_timerWidget(context, totalWorkingHours),
|
||||
16.height,
|
||||
AttachmentPicker(
|
||||
label: 'Upload Attachment',
|
||||
attachment: _attachments,
|
||||
buttonColor: AppColor.primary10,
|
||||
onlyImages: false,
|
||||
buttonIcon: 'attachment_icon'.toSvgAsset(
|
||||
color: AppColor.primary10,
|
||||
),
|
||||
),
|
||||
8.height,
|
||||
],
|
||||
).toShadowContainer(context),
|
||||
).expanded,
|
||||
FooterActionButton.footerContainer(
|
||||
context: context,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
AppFilledButton(
|
||||
label: context.translation.save,
|
||||
buttonColor: context.isDark ? AppColor.neutral70 : AppColor.white60,
|
||||
textColor: context.isDark ? AppColor.white10 : AppColor.black10,
|
||||
onPressed: () {
|
||||
log('button press ');
|
||||
formModel.isComplete = false;
|
||||
_onSubmit(context);
|
||||
}).expanded,
|
||||
12.width,
|
||||
AppFilledButton(
|
||||
label: context.translation.complete,
|
||||
buttonColor: AppColor.primary10,
|
||||
onPressed: () {
|
||||
formModel.isComplete = true;
|
||||
_onSubmit(context);
|
||||
}).expanded,
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)),
|
||||
),
|
||||
).handlePopScope(
|
||||
cxt: context,
|
||||
onSave: () {
|
||||
formModel.isComplete = false;
|
||||
_onSubmit(context);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _timerWidget(BuildContext context, double totalWorkingHours) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// AppTimer(
|
||||
// label: context.translation.timer,
|
||||
// timer: formModel.auditTimerModel,
|
||||
// // enabled: enableTimer,
|
||||
// pickerTimer: formModel.auditTimePicker,
|
||||
// pickerFromDate: DateTime.tryParse(widget.model?.createdDate ?? ''),
|
||||
// onPick: (time) {
|
||||
// formModel.auditTimePicker = time;
|
||||
// },
|
||||
// timerProgress: (isRunning) {},
|
||||
// onChange: (timer) async {
|
||||
// formModel.auditTimerModel = timer;
|
||||
// if (timer.startAt != null && timer.endAt != null) {
|
||||
// formModel.timerModelList = formModel.timerModelList ?? [];
|
||||
// formModel.timerModelList!.add(timer);
|
||||
// }
|
||||
// return true;
|
||||
// },
|
||||
// ),
|
||||
AppTimer(
|
||||
label: context.translation.workingHours,
|
||||
timer: formModel.auditTimerModel,
|
||||
pickerFromDate: DateTime.tryParse(widget.model?.createdDate ?? ''),
|
||||
pickerTimer: formModel.auditTimePicker,
|
||||
onPick: (time) {
|
||||
updateTimer(timer: time);
|
||||
},
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.fieldBgColor(context),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
timerProgress: (isRunning) {},
|
||||
onChange: (timer) async {
|
||||
updateTimer(timer: timer);
|
||||
log('here onChange ${timer.startAt}');
|
||||
|
||||
return true;
|
||||
},
|
||||
),
|
||||
if (totalWorkingHours > 0.0) ...[
|
||||
12.height,
|
||||
WorkingTimeTile(
|
||||
timerList: timerList,
|
||||
totalWorkingTime: totalWorkingHours,
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,327 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:test_sa/controllers/api_routes/api_manager.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/string_extensions.dart';
|
||||
import 'package:test_sa/extensions/text_extensions.dart';
|
||||
import 'package:test_sa/extensions/widget_extensions.dart';
|
||||
import 'package:test_sa/models/generic_attachment_model.dart';
|
||||
import 'package:test_sa/models/timer_model.dart';
|
||||
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.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/app_text_form_field.dart';
|
||||
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
|
||||
import 'package:test_sa/new_views/common_widgets/working_time_tile.dart';
|
||||
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
|
||||
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
|
||||
import 'package:test_sa/views/widgets/timer/app_timer.dart';
|
||||
import 'package:test_sa/views/widgets/total_working_time_detail_bottomsheet.dart';
|
||||
|
||||
class UpdateInternalAuditPage extends StatefulWidget {
|
||||
static const String id = "update-internal-audit";
|
||||
final model;
|
||||
|
||||
const UpdateInternalAuditPage({this.model, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<UpdateInternalAuditPage> createState() => _UpdateInternalAuditPageState();
|
||||
}
|
||||
|
||||
class _UpdateInternalAuditPageState extends State<UpdateInternalAuditPage> {
|
||||
final bool _isLoading = false;
|
||||
double totalWorkingHours = 0.0;
|
||||
late UserProvider _userProvider;
|
||||
|
||||
// GasRefillDetails _currentDetails = GasRefillDetails();
|
||||
final TextEditingController _commentController = TextEditingController();
|
||||
final TextEditingController _workingHoursController = TextEditingController();
|
||||
|
||||
// final GasRefillModel _formModel = GasRefillModel(gasRefillDetails: []);
|
||||
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
bool _firstTime = true;
|
||||
List<GenericAttachmentModel> _attachments = [];
|
||||
List<TimerHistoryModel> timerList = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// if (widget.gasRefillModel != null) {
|
||||
// _formModel.fromGasRefillModel(widget.gasRefillModel!);
|
||||
// _commentController.text = _formModel.techComment ?? "";
|
||||
// calculateWorkingTime();
|
||||
// try {
|
||||
// _deliveredQuantity = deliveredQuantity.singleWhere((element) => element.value == _formModel.gasRefillDetails![0].deliverdQty);
|
||||
// _currentDetails.deliverdQty = _deliveredQuantity!.value;
|
||||
// } catch (ex) {}
|
||||
// }
|
||||
// if (_formModel.gasRefillAttachments != null && _formModel.gasRefillAttachments!.isNotEmpty) {
|
||||
// _attachments.addAll(_formModel.gasRefillAttachments!.map((e) => GenericAttachmentModel(id:e.id,name:e.attachmentName!)).toList());
|
||||
// }
|
||||
}
|
||||
|
||||
void calculateWorkingTime() {
|
||||
// final timers = _formModel.gasRefillTimers ?? [];
|
||||
// totalWorkingHours = timers.fold<double>(0.0, (sum, item) {
|
||||
// if (item.startDate == null || item.endDate == null) return sum;
|
||||
// try {
|
||||
// final start = DateTime.parse(item.startDate!);
|
||||
// final end = DateTime.parse(item.endDate!);
|
||||
// final diffInHours = end.difference(start).inSeconds / 3600.0; // convert to hours
|
||||
// return sum + diffInHours;
|
||||
// } catch (_) {
|
||||
// return sum;
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// timerList = timers.map((e) {
|
||||
// return TimerHistoryModel(
|
||||
// id: e.id,
|
||||
// startTime: e.startDate,
|
||||
// endTime: e.endDate,
|
||||
// workingHours: e.workingHours,
|
||||
// );
|
||||
// }).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
void setState(VoidCallback fn) {
|
||||
if (mounted) super.setState(() {});
|
||||
}
|
||||
|
||||
_onSubmit(BuildContext context, int status) async {
|
||||
bool isTimerPickerEnable = ApiManager.instance.assetGroup?.enabledEngineerTimer ?? false;
|
||||
|
||||
// if (isTimerPickerEnable) {
|
||||
// if (_formModel.timer?.startAt == null && _formModel.gasRefillTimePicker == null) {
|
||||
// Fluttertoast.showToast(msg: "Working Hours Required");
|
||||
// return false;
|
||||
// }
|
||||
// if (_formModel.gasRefillTimePicker == null) {
|
||||
// if (_formModel.timer?.startAt == null) {
|
||||
// Fluttertoast.showToast(msg: "Working Hours Required");
|
||||
// return false;
|
||||
// }
|
||||
// if (_formModel.timer?.endAt == null) {
|
||||
// Fluttertoast.showToast(msg: "Please Stop The Timer");
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// if (_formModel.timer?.startAt == null) {
|
||||
// Fluttertoast.showToast(msg: "Working Hours Required");
|
||||
// return false;
|
||||
// }
|
||||
// if (_formModel.timer?.endAt == null) {
|
||||
// Fluttertoast.showToast(msg: "Please Stop The Timer");
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (_currentDetails.deliverdQty == null) {
|
||||
// await Fluttertoast.showToast(msg: "Delivered Quantity is Required");
|
||||
// return false;
|
||||
// }
|
||||
// _formModel.gasRefillDetails = [];
|
||||
// _formModel.gasRefillDetails?.add(_currentDetails);
|
||||
//
|
||||
// showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
|
||||
// _formModel.gasRefillTimers = _formModel.gasRefillTimers ?? [];
|
||||
// if (_formModel.gasRefillTimePicker != null) {
|
||||
// int durationInSecond = _formModel.gasRefillTimePicker!.endAt!.difference(_formModel.gasRefillTimePicker!.startAt!).inSeconds;
|
||||
// _formModel.gasRefillTimers?.add(
|
||||
// GasRefillTimer(
|
||||
// id: 0,
|
||||
// startDate: _formModel.gasRefillTimePicker!.startAt!.toIso8601String(), // Handle potential null
|
||||
// endDate: _formModel.gasRefillTimePicker!.endAt?.toIso8601String(), // Handle potential null
|
||||
// workingHours: ((durationInSecond) / 60 / 60),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// _formModel.timerModelList?.forEach((timer) {
|
||||
// int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds;
|
||||
// _formModel.gasRefillTimers?.add(
|
||||
// GasRefillTimer(
|
||||
// id: 0,
|
||||
// startDate: timer.startAt!.toIso8601String(), // Handle potential null
|
||||
// endDate: timer.endAt?.toIso8601String(), // Handle potential null
|
||||
// workingHours: ((durationInSecond) / 60 / 60),
|
||||
// ),
|
||||
// );
|
||||
// });
|
||||
// _formModel.gasRefillAttachments = [];
|
||||
// for (var item in _attachments) {
|
||||
// String fileName = ServiceRequestUtils.isLocalUrl(item.name??'') ? ("${item.name??''.split("/").last}|${base64Encode(File(item.name??'').readAsBytesSync())}") :item.name??'';
|
||||
// _formModel.gasRefillAttachments?.add(GasRefillAttachments(
|
||||
// id: item.id, gasRefillId: _formModel.id ?? 0, attachmentName: fileName));
|
||||
// }
|
||||
|
||||
// await _gasRefillProvider?.updateGasRefill(status: status, model: _formModel).then((success) {
|
||||
// Navigator.pop(context);
|
||||
// if (success) {
|
||||
// if (status == 1) {
|
||||
// AllRequestsProvider allRequestsProvider = Provider.of<AllRequestsProvider>(context, listen: false);
|
||||
// // when click complete then this request remove from the list and status changes to closed..
|
||||
// _gasRefillProvider?.reset();
|
||||
// allRequestsProvider.getAllRequests(context, typeTransaction: 2);
|
||||
// }
|
||||
// Navigator.pop(context);
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_commentController.dispose();
|
||||
_workingHoursController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void updateTimer({TimerModel? timer}) {
|
||||
// _formModel.timer = timer;
|
||||
// if (timer?.startAt != null && timer?.endAt != null) {
|
||||
// _formModel.timerModelList = _formModel.timerModelList ?? [];
|
||||
// _formModel.timerModelList!.add(timer!);
|
||||
// }
|
||||
// notifyListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_userProvider = Provider.of<UserProvider>(context);
|
||||
if (_firstTime) {
|
||||
String? clientName;
|
||||
// if (widget.gasRefillModel != null) {
|
||||
// _gasRefillProvider!.expectedDateTime = DateTime.tryParse(_formModel.expectedDate ?? "");
|
||||
// _formModel.timer = TimerModel(startAt: DateTime.tryParse(widget.gasRefillModel?.startDate ?? ""), endAt: DateTime.tryParse(widget.gasRefillModel?.endDate ?? ""));
|
||||
// } else {
|
||||
// _formModel.timer = null;
|
||||
// }
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: DefaultAppBar(
|
||||
title: 'Update Information'.addTranslation,
|
||||
onWillPopScope: () {
|
||||
_onSubmit(context, 0);
|
||||
},
|
||||
),
|
||||
key: _scaffoldKey,
|
||||
body: Form(
|
||||
key: _formKey,
|
||||
child: LoadingManager(
|
||||
isLoading: _isLoading,
|
||||
isFailedLoading: false,
|
||||
stateCode: 200,
|
||||
onRefresh: () async {},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
8.height,
|
||||
AppTextFormField(
|
||||
labelText: 'Debrief'.addTranslation,
|
||||
textInputType: TextInputType.multiline,
|
||||
hintStyle: TextStyle(color: context.isDark ? AppColor.white10 : AppColor.black10),
|
||||
labelStyle: TextStyle(color: context.isDark ? AppColor.white10 : AppColor.black10),
|
||||
alignLabelWithHint: true,
|
||||
backgroundColor: AppColor.fieldBgColor(context),
|
||||
showShadow: false,
|
||||
controller: _commentController,
|
||||
onChange: (value) {},
|
||||
onSaved: (value) {},
|
||||
),
|
||||
8.height,
|
||||
_timerWidget(context, totalWorkingHours),
|
||||
16.height,
|
||||
AttachmentPicker(
|
||||
label: context.translation.attachFiles,
|
||||
attachment: _attachments,
|
||||
buttonColor: AppColor.primary10,
|
||||
onlyImages: false,
|
||||
buttonIcon: 'image-plus'.toSvgAsset(
|
||||
color: AppColor.primary10,
|
||||
),
|
||||
),
|
||||
8.height,
|
||||
],
|
||||
).toShadowContainer(context),
|
||||
).expanded,
|
||||
FooterActionButton.footerContainer(
|
||||
context: context,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
AppFilledButton(
|
||||
label: context.translation.save,
|
||||
buttonColor: context.isDark ? AppColor.neutral70 : AppColor.white60,
|
||||
textColor: context.isDark ? AppColor.white10 : AppColor.black10,
|
||||
onPressed: () => _onSubmit(context, 0),
|
||||
).expanded,
|
||||
12.width,
|
||||
AppFilledButton(
|
||||
label: context.translation.complete,
|
||||
buttonColor: AppColor.primary10,
|
||||
onPressed: () => _onSubmit(context, 1),
|
||||
).expanded,
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)),
|
||||
),
|
||||
).handlePopScope(
|
||||
cxt: context,
|
||||
onSave: () {
|
||||
_onSubmit(context, 0);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _timerWidget(BuildContext context, double totalWorkingHours) {
|
||||
TimerModel? timer = TimerModel();
|
||||
TimerModel? timerPicker;
|
||||
List<TimerModel>? timerModelList = [];
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
AppTimer(
|
||||
label: context.translation.workingHours,
|
||||
timer: timer,
|
||||
// pickerFromDate: DateTime.tryParse(widget.gasRefillModel?.createdDate ?? ''),
|
||||
pickerFromDate: DateTime.tryParse(''),
|
||||
pickerTimer: timerPicker,
|
||||
onPick: (time) {
|
||||
//timerPicker = time;
|
||||
},
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.fieldBgColor(context),
|
||||
// color: AppColor.neutral100,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
timerProgress: (isRunning) {},
|
||||
onChange: (timer) async {
|
||||
updateTimer(timer: timer);
|
||||
return true;
|
||||
},
|
||||
),
|
||||
if (totalWorkingHours > 0.0) ...[
|
||||
12.height,
|
||||
WorkingTimeTile(
|
||||
timerList: timerList,
|
||||
totalWorkingTime: totalWorkingHours,
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:http/http.dart';
|
||||
import 'package:test_sa/controllers/api_routes/api_manager.dart';
|
||||
import 'package:test_sa/controllers/api_routes/urls.dart';
|
||||
import 'package:test_sa/models/lookup.dart';
|
||||
import 'package:test_sa/providers/loading_list_notifier.dart';
|
||||
|
||||
class InternalAuditWoTypeProvider extends LoadingListNotifier<Lookup> {
|
||||
@override
|
||||
Future getData({int? id}) async {
|
||||
if (loading ?? false) return -2;
|
||||
loading = true;
|
||||
notifyListeners();
|
||||
Response response;
|
||||
try {
|
||||
response = await ApiManager.instance.get(URLs.getInternalAuditWoType);
|
||||
} catch (error) {
|
||||
loading = false;
|
||||
stateCode = -1;
|
||||
notifyListeners();
|
||||
return -1;
|
||||
}
|
||||
stateCode = response.statusCode;
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
List listJson = json.decode(response.body)["data"];
|
||||
items = listJson.map((department) => Lookup.fromJson(department)).toList();
|
||||
}
|
||||
loading = false;
|
||||
notifyListeners();
|
||||
return response.statusCode;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue