attachment fixes

design_3.0_internal_audit_module
WaseemAbbasi22 2 months ago
parent 81dd189025
commit a04ae0c833

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

@ -322,6 +322,7 @@ class URLs {
static get addOrUpdateInternalAuditSystem => "$_baseUrl/InternalAuditSystems/AddOrUpdateInternalAuditSystem";
static get getWoAutoComplete => "$_baseUrl/InternalAuditSystems/AutoCompleteAllWorkOrder";
static get updateAuditEquipmentsEngineer => "$_baseUrl/InternalAuditEquipments/UpdateAuditEquipmentsEngineer";
static get updateAuditSystemEngineer => "$_baseUrl/InternalAuditSystems/UpdateAuditSystemEngineer";
static get loadAllWorkOrderDetailsByID => "$_baseUrl/InternalAuditSystems/LoadAllWorkOrderDetailsByID";
}

@ -31,6 +31,7 @@ import 'package:test_sa/modules/cm_module/service_request_detail_provider.dart';
import 'package:test_sa/modules/cm_module/views/nurse/create_new_request_view.dart';
import 'package:test_sa/modules/internal_audit_module/pages/equipment_internal_audit/create_equipment_internal_audit_form.dart';
import 'package:test_sa/modules/internal_audit_module/pages/system_internal_audit/create_system_internal_audit_form.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_finding_type_provider.dart';
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_provider.dart';
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_wo_type_provider.dart';
@ -365,7 +366,8 @@ class MyApp extends StatelessWidget {
HelpCenterPage.id: (_) => const HelpCenterPage(),
CreateEquipmentInternalAuditForm.id: (_) => const CreateEquipmentInternalAuditForm(),
CreateSystemInternalAuditForm.id: (_) => const CreateSystemInternalAuditForm(),
UpdateEquipmentInternalAuditPage.id: (_) => UpdateEquipmentInternalAuditPage(),
UpdateEquipmentInternalAuditPage.id: (_) => UpdateEquipmentInternalAuditPage(),
UpdateSystemInternalAuditPage.id: (_) => UpdateSystemInternalAuditPage(),
// SwipeSuccessView.routeName: (_) => const SwipeSuccessView(),
// SwipeHistoryView.routeName: (_) => const SwipeHistoryView(),
},

@ -31,11 +31,11 @@ class ActivityMaintenanceHelperModel {
WorkOrderAssignedEmployee? assignedEmployee;
SuppEngineerWorkOrders? supEngineer;
ActivityMaintenanceAssistantEmployees? modelAssistantEmployees;
List<AssistantEmployeesModel>? assistantEmployList=[];
List<AssistantEmployees>? assistantEmployees;
List<ActivityMaintenanceTimers>? activityMaintenanceTimers = [];
TimerModel? activityMaintenanceTimerModel = TimerModel();
TimerModel? activityTimePicker;
List<AssistantEmployeesModel>? assistantEmployList=[];
List<TimerModel>? timerModelList = [];
ActivityMaintenanceHelperModel(

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

@ -1,4 +1,5 @@
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';
@ -15,6 +16,8 @@ class EquipmentInternalAuditDataModel {
String? remarks;
List<EquipmentsFinding>? equipmentsFindings;
List<InternalAuditAttachments>? attachments;
EngineerData? engineerData;
EquipmentInternalAuditDataModel({
this.id,
@ -29,6 +32,7 @@ class EquipmentInternalAuditDataModel {
this.remarks,
this.equipmentsFindings,
this.attachments,
this.engineerData,
});
EquipmentInternalAuditDataModel.fromJson(Map<String, dynamic> json) {
@ -48,7 +52,14 @@ class EquipmentInternalAuditDataModel {
equipmentsFindings!.add(EquipmentsFinding.fromJson(v));
});
}
// attachments = json['attachments'] != null ? List<InternalAuditAttachments>.from(json['attachments']) : [];
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() {
@ -76,6 +87,7 @@ class EquipmentInternalAuditDataModel {
equipmentsFindings!.map((v) => v.toJson()).toList();
}
data['attachments'] = attachments;
if (engineerData != null) data['engineerData'] = engineerData!.toJson();
return data;
}
}

@ -1,23 +1,27 @@
import 'dart:developer';
class InternalAuditAttachments {
InternalAuditAttachments({this.id,this.originalName, this.name,this.createdBy});
InternalAuditAttachments({this.id, this.originalName, this.name, this.createdBy});
int? id;
String? name;
String? originalName;
String ?createdBy;
String? createdBy;
InternalAuditAttachments.fromJson(Map<String, dynamic> json) {
log('name is ${json['name']}');
id = json['id'];
name = json['name'];
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['id'] = id;
data['name'] = name;
data['originalName'] = originalName;
// data['createdBy'] = createdBy;
return data;
}
}
}

@ -1,4 +1,6 @@
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 {
@ -17,6 +19,8 @@ class SystemInternalAuditDataModel {
String? createdDate;
String? modifiedBy;
String? modifiedDate;
List<InternalAuditAttachments>? attachments;
EngineerData? engineerData;
SystemInternalAuditDataModel({
this.id,
@ -34,6 +38,8 @@ class SystemInternalAuditDataModel {
this.createdDate,
this.modifiedBy,
this.modifiedDate,
this.attachments,
this.engineerData,
});
SystemInternalAuditDataModel.fromJson(Map<String, dynamic> json) {
@ -52,6 +58,13 @@ class SystemInternalAuditDataModel {
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() {
@ -71,6 +84,7 @@ class SystemInternalAuditDataModel {
data['createdDate'] = createdDate;
data['modifiedBy'] = modifiedBy;
data['modifiedDate'] = modifiedDate;
if (engineerData != null) data['engineerData'] = engineerData!.toJson();
return data;
}
}
@ -120,3 +134,5 @@ class Auditor {
return data;
}
}

@ -1,7 +1,7 @@
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;
@ -13,12 +13,13 @@ class SystemInternalAuditFormModel {
int? correctiveMaintenanceId;
int? planPreventiveVisitId;
int? assetTransferId;
List<InternalAuditAttachments>? attachments = [];
int? taskJobId;
int? taskAlertJobId;
int? gasRefillId;
int? planRecurrentTaskId;
int? statusId;
SystemAuditWorkOrderDetailModel ?workOrderDetailModel;
SystemAuditWorkOrderDetailModel? workOrderDetailModel;
SystemInternalAuditFormModel({
this.id,
@ -36,6 +37,7 @@ class SystemInternalAuditFormModel {
this.planRecurrentTaskId,
this.workOrderDetailModel,
this.statusId,
this.attachments,
});
Map<String, dynamic> toJson() {
@ -54,6 +56,7 @@ class SystemInternalAuditFormModel {
'gasRefillId': gasRefillId,
'planRecurrentTaskId': planRecurrentTaskId,
'statusId': statusId,
'attachments': attachments?.map((e) => e.toJson()).toList(),
};
}
}
@ -73,12 +76,13 @@ class WoAutoCompleteModel {
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] =id;
data['id'] = id;
data['woOrderNo'] = workOrderNo;
data['displayName'] = workOrderNo;
return data;
}
}
class SystemAuditWorkOrderDetailModel {
String? createdBy;
DateTime? createdDate;
@ -196,6 +200,3 @@ class SystemAuditWorkOrderDetailModel {
};
}
}

@ -1,5 +1,6 @@
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;
@ -12,19 +13,24 @@ class AuditFormModel {
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,
});
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'];
@ -34,9 +40,7 @@ class AuditFormModel {
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();
attachments = (json['attachments'] as List).map((e) => InternalAuditAttachments.fromJson(e)).toList();
}
isComplete = json['isComplete'];
}
@ -48,9 +52,10 @@ class AuditFormModel {
'debrief': debrief,
'startTime': startTime?.toIso8601String(),
'endTime': endTime?.toIso8601String(),
// 'auditTimer': auditTimers,
'totalHours': totalHours,
'attachments': attachments?.map((e) => e.toJson()).toList(),
'isComplete': isComplete,
};
}
}
}

@ -111,7 +111,7 @@ class _CreateEquipmentInternalAuditFormState extends State<CreateEquipmentIntern
buttonColor: AppColor.primary10,
onlyImages: false,
onChange: (value) {},
buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.primary10),
buttonIcon: 'attachment_icon'.toSvgAsset(color: AppColor.primary10),
),
],
).toShadowContainer(context),

@ -2,6 +2,7 @@ import 'dart:io';
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';
@ -9,11 +10,13 @@ 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/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/pages/equipment_internal_audit/update_equipment_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';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
@ -34,6 +37,7 @@ class _EquipmentInternalAuditDetailPageState extends State<EquipmentInternalAudi
bool isWoType = true;
EquipmentInternalAuditDataModel? model;
late InternalAuditProvider _internalAuditProvider;
List<InternalAuditAttachments> allAttachments = [];
@override
void initState() {
@ -46,6 +50,13 @@ class _EquipmentInternalAuditDetailPageState extends State<EquipmentInternalAudi
Future<void> getAuditData() async {
model = await _internalAuditProvider.getEquipmentInternalAuditById(widget.auditId);
allAttachments.clear();
allAttachments = [
...(model?.attachments ?? []),
...(model?.engineerData?.attachments ?? []),
];
}
@override
@ -62,8 +73,8 @@ class _EquipmentInternalAuditDetailPageState extends State<EquipmentInternalAudi
selector: (_, provider) => provider.isLoading,
builder: (_, isLoading, __) {
if (isLoading) return const ALoading();
if (model==null) return NoDataFound(message: context.translation.noDataFound).center;
return Column(
if (model == null) return NoDataFound(message: context.translation.noDataFound).center;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SingleChildScrollView(
@ -76,24 +87,19 @@ class _EquipmentInternalAuditDetailPageState extends State<EquipmentInternalAudi
requestDetails(),
8.height,
if (model?.remarks?.isNotEmpty ?? false) ...[
const Divider().defaultStyle(context),
model!.remarks!.bodyText(context),
8.height,
],
if (allAttachments.isNotEmpty) ...[
const Divider().defaultStyle(context),
Text(
"Remarks".addTranslation,
"Attachments".addTranslation,
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
model!.remarks!.bodyText(context),
8.height,
FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
],
//TODO need to check for attachments backend need to fix the name they are sending wrong string
// if (model!.attachments!.isNotEmpty) ...[
// const Divider().defaultStyle(context),
// Text(
// "Attachments".addTranslation,
// style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
// ),
// 8.height,
// FilesList(images: model!.attachments!.map((e) => URLs.getFileUrl(e.name ?? '') ?? '').toList() ?? []),
// ],
],
).paddingAll(0).toShadowContainer(context),
).expanded,
@ -103,8 +109,17 @@ class _EquipmentInternalAuditDetailPageState extends State<EquipmentInternalAudi
child: AppFilledButton(
buttonColor: AppColor.primary10,
label: "Update",
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdateEquipmentInternalAuditPage(model: model)));
onPressed: () async {
final result = await Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => UpdateEquipmentInternalAuditPage(model: model),
),
);
if (result == true) {
await getAuditData();
setState(() {}); // refresh UI with new model
}
// Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdateEquipmentInternalAuditPage(model: model)));
}),
),
],

@ -2,9 +2,9 @@ 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/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';
@ -14,12 +14,14 @@ 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/audit_form_model.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';
@ -32,7 +34,7 @@ class UpdateEquipmentInternalAuditPage extends StatefulWidget {
static const String id = "update-equipment-internal-audit";
EquipmentInternalAuditDataModel? model;
UpdateEquipmentInternalAuditPage({Key? key,this.model}) : super(key: key);
UpdateEquipmentInternalAuditPage({Key? key, this.model}) : super(key: key);
@override
State<UpdateEquipmentInternalAuditPage> createState() => _UpdateEquipmentInternalAuditPageState();
@ -46,6 +48,7 @@ class _UpdateEquipmentInternalAuditPageState extends State<UpdateEquipmentIntern
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 = [];
@ -54,137 +57,93 @@ class _UpdateEquipmentInternalAuditPageState extends State<UpdateEquipmentIntern
populateForm();
super.initState();
}
void populateForm(){
void populateForm() {
formModel.requestId = widget.model?.id;
formModel.id = widget.model?.id;
_attachments = widget.model?.attachments?.map((e) => GenericAttachmentModel(id: e.id?.toInt()??0, name: e.name!)).toList() ?? [];
_attachments = widget.model?.engineerData?.attachments?.map((e) => GenericAttachmentModel(id: e.id?.toInt() ?? 0, name: e.name!)).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();
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);
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 ?? '';
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,
name: fileName,
),
);
}
provider.updateEquipmentInternalAudit(model: formModel);
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');
}
log('payload ${formModel.toJson()}');
// 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
@ -206,7 +165,6 @@ class _UpdateEquipmentInternalAuditPageState extends State<UpdateEquipmentIntern
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -251,11 +209,11 @@ class _UpdateEquipmentInternalAuditPageState extends State<UpdateEquipmentIntern
_timerWidget(context, totalWorkingHours),
16.height,
AttachmentPicker(
label: context.translation.attachFiles,
label: 'Upload Attachment',
attachment: _attachments,
buttonColor: AppColor.primary10,
onlyImages: false,
buttonIcon: 'image-plus'.toSvgAsset(
buttonIcon: 'attachment_icon'.toSvgAsset(
color: AppColor.primary10,
),
),
@ -269,23 +227,21 @@ class _UpdateEquipmentInternalAuditPageState extends State<UpdateEquipmentIntern
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,
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: (){
label: context.translation.complete,
buttonColor: AppColor.primary10,
onPressed: () {
formModel.isComplete = true;
_onSubmit(context);
}
).expanded,
}).expanded,
],
),
),
@ -295,26 +251,49 @@ class _UpdateEquipmentInternalAuditPageState extends State<UpdateEquipmentIntern
).handlePopScope(
cxt: context,
onSave: () {
formModel.isComplete=false;
formModel.isComplete = false;
_onSubmit(context);
});
}
Widget _timerWidget(BuildContext context, double totalWorkingHours) {
TimerModel? timer = TimerModel();
TimerModel? timerPicker;
List<TimerModel>? timerModelList = [];
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: timer,
timer: formModel.auditTimerModel,
pickerFromDate: DateTime.tryParse(widget.model?.createdDate ?? ''),
pickerTimer: timerPicker,
onPick: (time) {
updateTimer(timer: timer);
pickerTimer: formModel.auditTimePicker,
onPick: (timer) {
updateTimer(timer: timer);
},
width: double.infinity,
decoration: BoxDecoration(

@ -15,6 +15,7 @@ import 'package:test_sa/models/lookup.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/equipment_internal_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/models/system_internal_audit_form_model.dart';
import 'package:test_sa/modules/internal_audit_module/pages/system_internal_audit/system_audit_work_order_auto_complete_field.dart';
import 'package:test_sa/modules/internal_audit_module/provider/internal_audit_checklist_provider.dart';
@ -47,7 +48,7 @@ class _CreateSystemInternalAuditFormState extends State<CreateSystemInternalAudi
final SystemInternalAuditFormModel _model = SystemInternalAuditFormModel();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final List<GenericAttachmentModel> _deviceImages = [];
final List<GenericAttachmentModel> _attachments = [];
late TextEditingController _woAutoCompleteController;
bool showLoading = false;
@ -148,15 +149,14 @@ class _CreateSystemInternalAuditFormState extends State<CreateSystemInternalAudi
_model.findingDescription = value;
},
),
//TODO Not Avaliable in CR and API
// 16.height,
// AttachmentPicker(
// label: context.translation.attachments,
// attachment: _deviceImages,
// buttonColor: AppColor.primary10,
// onlyImages: false,
// buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.primary10),
// ),
16.height,
AttachmentPicker(
label: context.translation.attachments,
attachment: _attachments,
buttonColor: AppColor.primary10,
onlyImages: false,
buttonIcon: 'attachment_icon'.toSvgAsset(color: AppColor.primary10),
),
],
).toShadowContainer(context),
).expanded,
@ -178,6 +178,11 @@ class _CreateSystemInternalAuditFormState extends State<CreateSystemInternalAudi
InternalAuditProvider internalAuditProvider = Provider.of<InternalAuditProvider>(context, listen: false);
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
_model.attachments=[];
for (var item in _attachments) {
String fileName = ServiceRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
_model.attachments?.add(InternalAuditAttachments(id: item.id, name: fileName));
}
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
_model.auditorId = context.userProvider.user?.userID;
bool status = await internalAuditProvider.addSystemInternalAudit(context: context, request: _model);

@ -1,19 +1,24 @@
import 'dart:io';
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 {
@ -30,8 +35,9 @@ class SystemInternalAuditDetailPage extends StatefulWidget {
class _SystemInternalAuditDetailPageState extends State<SystemInternalAuditDetailPage> {
bool isWoType = true;
// EquipmentInternalAuditDataModel? model;
SystemInternalAuditDataModel? model;
late InternalAuditProvider _internalAuditProvider;
List<InternalAuditAttachments> allAttachments = [];
@override
void initState() {
@ -43,7 +49,12 @@ class _SystemInternalAuditDetailPageState extends State<SystemInternalAuditDetai
}
Future<void> getAuditData() async {
await _internalAuditProvider.getInternalSystemAuditById(widget.auditId);
model = await _internalAuditProvider.getInternalSystemAuditById(widget.auditId);
allAttachments.clear();
allAttachments = [
...(model?.attachments ?? []),
...(model?.engineerData?.attachments ?? []),
];
}
@override
@ -70,28 +81,27 @@ class _SystemInternalAuditDetailPageState extends State<SystemInternalAuditDetai
children: [
assetInformation(),
8.height,
isWoType ? workOrderInformation() : requestDetails(),
workOrderInformation(),
8.height,
//TODO need to check for comments
// if (model.comment?.isNotEmpty ?? false) ...[
const Divider().defaultStyle(context),
Text(
"Comments".addTranslation,
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
// model.comment!.bodyText(context),
// 8.height,
// ],
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 ( _model.attachment.isNotEmpty) ...[
const Divider().defaultStyle(context),
Text(
"Attachments".addTranslation,
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
8.height,
// FilesList(images: _model.attachment?.map((e) => URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList() ?? []),
// ],
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,
@ -101,8 +111,16 @@ class _SystemInternalAuditDetailPageState extends State<SystemInternalAuditDetai
child: AppFilledButton(
buttonColor: AppColor.primary10,
label: "Update",
onPressed: () {
Navigator.pushNamed(context, UpdateEquipmentInternalAuditPage.id);
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
}
}),
),
],
@ -112,6 +130,7 @@ class _SystemInternalAuditDetailPageState extends State<SystemInternalAuditDetai
}
Widget workOrderInformation() {
final details = model?.workOrderDetails;
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
@ -122,12 +141,12 @@ class _SystemInternalAuditDetailPageState extends State<SystemInternalAuditDetai
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
6.height,
'${context.translation.woNumber}: ${'-'}'.bodyText(context),
'${'WO Type'.addTranslation}: ${'-'}'.bodyText(context),
'${context.translation.site}: ${'-'}'.bodyText(context),
'${context.translation.assetName}: ${'-'}'.bodyText(context),
'${context.translation.manufacture}: ${'-'}'.bodyText(context),
'${context.translation.model}: ${'-'}'.bodyText(context),
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),
],
);
}
@ -150,6 +169,7 @@ class _SystemInternalAuditDetailPageState extends State<SystemInternalAuditDetai
}
Widget assetInformation() {
final details = model?.workOrderDetails;
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
@ -159,14 +179,28 @@ class _SystemInternalAuditDetailPageState extends State<SystemInternalAuditDetai
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
6.height,
'${context.translation.assetName}: ${'-'}'.bodyText(context),
'${context.translation.assetNo}: ${'-'}'.bodyText(context),
'${context.translation.manufacture}: ${'-'}'.bodyText(context),
'${context.translation.model}: ${'-'}'.bodyText(context),
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,

@ -1,9 +1,10 @@
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/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';
@ -11,10 +12,16 @@ 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/equipment_internal_audit_data_model.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';
@ -23,168 +30,149 @@ 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 {
class UpdateSystemInternalAuditPage extends StatefulWidget {
static const String id = "update-system-internal-audit";
//Need to pass system model here.
final EquipmentInternalAuditDataModel ?model;
SystemInternalAuditDataModel? model;
const UpdateInternalAuditPage({this.model, Key? key}) : super(key: key);
UpdateSystemInternalAuditPage({Key? key, this.model}) : super(key: key);
@override
State<UpdateInternalAuditPage> createState() => _UpdateInternalAuditPageState();
State<UpdateSystemInternalAuditPage> createState() => _UpdateSystemInternalAuditPageState();
}
class _UpdateInternalAuditPageState extends State<UpdateInternalAuditPage> {
class _UpdateSystemInternalAuditPageState extends State<UpdateSystemInternalAuditPage> {
final bool _isLoading = false;
double totalWorkingHours = 0.0;
late UserProvider _userProvider;
final TextEditingController _commentController = TextEditingController();
AuditFormModel formModel = AuditFormModel();
final TextEditingController _workingHoursController = TextEditingController();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
bool _firstTime = true;
List<GenericAttachmentModel> _attachments = [];
//TODO need to check if it's needed or not..
List<TimerHistoryModel> timerList = [];
@override
void initState() {
populateForm();
super.initState();
}
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();
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();
}
@override
void setState(VoidCallback fn) {
if (mounted) super.setState(() {});
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, int status) async {
_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());
// 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));
// }
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),
),
);
});
// 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);
// }
// });
_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() {
_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();
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) {
_userProvider = Provider.of<UserProvider>(context);
return Scaffold(
appBar: DefaultAppBar(
title: 'Update Information'.addTranslation,
onWillPopScope: () {
_onSubmit(context, 0);
formModel.isComplete = false;
_onSubmit(context);
},
),
key: _scaffoldKey,
@ -210,21 +198,22 @@ class _UpdateInternalAuditPageState extends State<UpdateInternalAuditPage> {
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,
controller: _commentController,
onChange: (value) {},
onSaved: (value) {},
onSaved: (value) {
formModel.debrief = value;
},
),
8.height,
_timerWidget(context, totalWorkingHours),
16.height,
AttachmentPicker(
label: context.translation.attachFiles,
label: 'Upload Attachment',
attachment: _attachments,
buttonColor: AppColor.primary10,
onlyImages: false,
buttonIcon: 'image-plus'.toSvgAsset(
buttonIcon: 'attachment_icon'.toSvgAsset(
color: AppColor.primary10,
),
),
@ -238,17 +227,22 @@ class _UpdateInternalAuditPageState extends State<UpdateInternalAuditPage> {
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,
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: () => _onSubmit(context, 1),
).expanded,
label: context.translation.complete,
buttonColor: AppColor.primary10,
onPressed: () {
formModel.isComplete = true;
_onSubmit(context);
}).expanded,
],
),
),
@ -258,35 +252,52 @@ class _UpdateInternalAuditPageState extends State<UpdateInternalAuditPage> {
).handlePopScope(
cxt: context,
onSave: () {
_onSubmit(context, 0);
formModel.isComplete = false;
_onSubmit(context);
});
}
Widget _timerWidget(BuildContext context, double totalWorkingHours) {
TimerModel? timer = TimerModel();
TimerModel? timerPicker;
List<TimerModel>? timerModelList = [];
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: timer,
// pickerFromDate: DateTime.tryParse(widget.gasRefillModel?.createdDate ?? ''),
pickerFromDate: DateTime.tryParse(''),
pickerTimer: timerPicker,
timer: formModel.auditTimerModel,
pickerFromDate: DateTime.tryParse(widget.model?.createdDate ?? ''),
pickerTimer: formModel.auditTimePicker,
onPick: (time) {
//timerPicker = time;
updateTimer(timer: 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);
log('here onChange ${timer.startAt}');
return true;
},
),

@ -10,9 +10,10 @@ import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/device/asset_search.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/new_models/asset_nd_auto_complete_by_dynamic_codes_model.dart';
import 'package:test_sa/modules/internal_audit_module/models/audit_form_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/equipment_internal_audit_form_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/system_internal_audit_form_model.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
@ -57,22 +58,30 @@ class InternalAuditProvider extends ChangeNotifier {
}
}
Future<int> getInternalSystemAuditById(int id) async {
Future<SystemInternalAuditDataModel?> getInternalSystemAuditById(int id) async {
try {
isLoading = true;
notifyListeners();
Response response = await ApiManager.instance.get("${URLs.getInternalAuditSystemById}?AuditSystemId=$id");
if (response.statusCode >= 200 && response.statusCode < 300) {}
isLoading = false;
notifyListeners();
return 0;
if (response.statusCode >= 200 && response.statusCode < 300) {
final decodedBody = jsonDecode(response.body);
SystemInternalAuditDataModel model = SystemInternalAuditDataModel.fromJson(decodedBody["data"]);
isLoading = false;
notifyListeners();
return model;
} else {
isLoading = false;
notifyListeners();
return null;
}
} catch (error) {
isLoading = false;
notifyListeners();
return -1;
return null;
}
}
Future<SystemAuditWorkOrderDetailModel?> loadAllWorkOrderDetailsByID({required int workOrderTypeId,required int workOrderId}) async {
Future<SystemAuditWorkOrderDetailModel?> loadAllWorkOrderDetailsByID({required int workOrderTypeId, required int workOrderId}) async {
try {
isLoading = true;
notifyListeners();
@ -94,6 +103,7 @@ class InternalAuditProvider extends ChangeNotifier {
return null;
}
}
Future<bool> updateEquipmentInternalAudit({required AuditFormModel model}) async {
isLoading = true;
Response response;
@ -114,6 +124,27 @@ class InternalAuditProvider extends ChangeNotifier {
}
}
Future<bool> updateSystemInternalAudit({required AuditFormModel model}) async {
isLoading = true;
Response response;
try {
response = await ApiManager.instance.put(URLs.updateAuditSystemEngineer, body: model.toJson());
stateCode = response.statusCode;
isLoading = false;
notifyListeners();
log('status code ${stateCode}');
if (stateCode == 200) {
return true;
}
return false;
} catch (error) {
isLoading = false;
stateCode = -1;
notifyListeners();
return false;
}
}
Future<bool> addEquipmentInternalAudit({
required BuildContext context,
required EquipmentInternalAuditFormModel request,
@ -137,6 +168,7 @@ class InternalAuditProvider extends ChangeNotifier {
return status;
}
}
Future<bool> addSystemInternalAudit({
required BuildContext context,
required SystemInternalAuditFormModel request,

Loading…
Cancel
Save