gas refill and asset transfer ui completed waiting for api

design_3.0_task_module_new
WaseemAbbasi22 8 months ago
parent c9b3538720
commit 3f90630db9

@ -3,12 +3,12 @@ class URLs {
static const String appReleaseBuildNumber = "14";
// static const host1 = "https://atomsm.hmg.com"; // production url
// static const host1 = "https://atomsmdev.hmg.com"; // local DEV url
static const host1 = "https://atomsmuat.hmg.com"; // local UAT url
static const host1 = "https://atomsmdev.hmg.com"; // local DEV url
// static const host1 = "https://atomsmuat.hmg.com"; // local UAT url
// static String _baseUrl = "$_host/mobile";
// static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis
static final String _baseUrl = "$_host/mobile"; // host local UAT
static final String _baseUrl = "$_host/v2/mobile"; // new V2 apis
// static final String _baseUrl = "$_host/mobile"; // host local UAT
// static final String _baseUrl = "$_host/v3/mobile"; // new V3 apis
static String _host = host1;

@ -1,5 +1,6 @@
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
@ -9,6 +10,7 @@ import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/models/hospital.dart';
import 'package:test_sa/models/new_models/gas_refill_model.dart';
import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/models/user.dart';
import '../../../new_views/common_widgets/app_lazy_loading.dart';
@ -43,6 +45,16 @@ class GasRefillProvider extends ChangeNotifier {
// done _loading = true
// failed _loading = false
bool isLoading = false;
List<File> _gasRefillAttachments = [];
List<File> get gasRefillAttachments => _gasRefillAttachments;
set gasRefillAttachments(List<File> value) {
_gasRefillAttachments = value;
notifyListeners();
}
Future<GasRefillModel?> getGasRefillObjectById(num id) async {
try {
@ -58,6 +70,15 @@ class GasRefillProvider extends ChangeNotifier {
}
}
// void updateRecurrentWoTimer({TimerModel? timer}) {
// recurrentWoData?.recurrentWoTimerModel = timer;
// if (timer?.startAt != null && timer?.endAt != null) {
// recurrentWoData?.timerModelList = recurrentWoData?.timerModelList ?? [];
// recurrentWoData?.timerModelList!.add(timer!);
// }
// notifyListeners();
// }
/// return -2 if request in progress
/// return -1 if error happen when sending request
/// return state code if request complete may be 200, 404 or 403

@ -71,6 +71,7 @@ import 'package:test_sa/views/pages/device_transfer/asset_search_screen.dart';
import 'package:test_sa/views/pages/device_transfer/request_device_transfer.dart';
import 'package:test_sa/views/pages/device_transfer/track_device_transfer.dart';
import 'package:test_sa/views/pages/sub_workorder/create_sub_workorder_page.dart';
import 'package:test_sa/views/pages/user/gas_refill/gas_refill_form.dart';
import 'package:test_sa/views/pages/user/gas_refill/request_gas_refill.dart';
import 'package:test_sa/views/pages/user/gas_refill/track_gas_refill.dart';
import 'package:test_sa/views/pages/user/notifications/notifications_page.dart';
@ -293,6 +294,7 @@ class MyApp extends StatelessWidget {
ServiceRequestsPage.id: (_) => const ServiceRequestsPage(),
//ReportIssuesPage.id: (_) => ReportIssuesPage(),
RequestGasRefill.id: (_) => const RequestGasRefill(),
GasRefillForm.id: (_) => const GasRefillForm(),
CreateServiceRequestPage.id: (_) => const CreateServiceRequestPage(),
CreateNewRequest.id: (_) => const CreateNewRequest(),
// SingleHospitalPicker.id: (_) => SingleHospitalPicker(),

@ -8,75 +8,77 @@ import 'package:test_sa/models/timer_model.dart';
import 'asset_transfer_attachment.dart';
class AssetTransfer {
AssetTransfer(
{this.id,
this.transferNo,
this.transferCode,
this.assetId,
this.destSiteId,
this.destBuildingId,
this.destFloorId,
this.destDepartmentId,
this.destRoomId,
this.senderSiteId,
this.senderBuildingId,
this.senderFloorId,
this.senderDepartmentId,
this.senderRoom,
this.senderAssignedEmployeeId,
this.senderMachineStatusId,
this.senderComment,
this.comment,
this.receiverEndUserId,
this.receiverEndUserName,
this.senderStartDate,
this.senderEndDate,
this.senderWorkingHours,
this.senderTravelingHours,
this.senderEngSignature,
this.senderAttachments,
this.receiverAssignedEmployeeId,
this.receiverMachineStatusId,
this.receiverComment,
this.receiverStartDate,
this.receiverEndDate,
this.receiverWorkingHours,
this.receiverTravelingHours,
this.receiverEngSignature,
this.receiverAttachments,
this.assetNumber,
this.assetName,
this.manufacturerName,
this.modelName,
this.assetSerialNo,
this.destDepartmentName,
this.destBuildingName,
this.applied,
this.extensionNo,
this.name,
this.employeeId,
this.createdDate,
this.createdOn,
this.destFloorName,
this.destSiteName,
this.manufacturerId,
this.modelId,
this.modifiedOn,
this.receiverAssignedEmployeeName,
this.receiverEngSignatureUrl,
this.receiverMachineStatusName,
this.senderAssignedEmployeeName,
this.senderBuildingName,
this.senderDepartmentName,
this.senderEngSignatureUrl,
this.senderFloorName,
this.senderMachineStatusName,
this.senderSiteName,
this.supplierId,
this.supplierName,
this.senderVisitTimers,
this.receiverVisitTimers,
this.tbsTimer});
AssetTransfer({
this.id,
this.transferNo,
this.transferCode,
this.assetId,
this.destSiteId,
this.destBuildingId,
this.destFloorId,
this.destDepartmentId,
this.destRoomId,
this.senderSiteId,
this.senderBuildingId,
this.senderFloorId,
this.senderDepartmentId,
this.senderRoom,
this.senderAssignedEmployeeId,
this.senderMachineStatusId,
this.senderComment,
this.comment,
this.receiverEndUserId,
this.receiverEndUserName,
this.senderStartDate,
this.senderEndDate,
this.senderWorkingHours,
this.senderTravelingHours,
this.senderEngSignature,
this.senderAttachments,
this.receiverAssignedEmployeeId,
this.receiverMachineStatusId,
this.receiverComment,
this.receiverStartDate,
this.receiverEndDate,
this.receiverWorkingHours,
this.receiverTravelingHours,
this.receiverEngSignature,
this.receiverAttachments,
this.assetNumber,
this.assetName,
this.manufacturerName,
this.modelName,
this.assetSerialNo,
this.destDepartmentName,
this.destBuildingName,
this.applied,
this.extensionNo,
this.name,
this.employeeId,
this.createdDate,
this.createdOn,
this.destFloorName,
this.destSiteName,
this.manufacturerId,
this.modelId,
this.modifiedOn,
this.receiverAssignedEmployeeName,
this.receiverEngSignatureUrl,
this.receiverMachineStatusName,
this.senderAssignedEmployeeName,
this.senderBuildingName,
this.senderDepartmentName,
this.senderEngSignatureUrl,
this.senderFloorName,
this.senderMachineStatusName,
this.senderSiteName,
this.supplierId,
this.supplierName,
this.senderVisitTimers,
this.receiverVisitTimers,
this.tbsTimer,
this.timerModelList,
});
AssetTransfer.fromJson(dynamic json) {
id = json['id'];
@ -250,6 +252,7 @@ class AssetTransfer {
String? modifiedOn;
List<VisitTimers>? senderVisitTimers;
List<VisitTimers>? receiverVisitTimers;
List<TimerModel>? timerModelList = [];
TimerModel? tbsTimer = TimerModel();
AssetTransfer copyWith(
@ -375,10 +378,10 @@ class AssetTransfer {
receiverMachineStatusName: receiverMachineStatusName ?? this.receiverMachineStatusName,
receiverEngSignatureUrl: receiverEngSignatureUrl ?? this.receiverEngSignatureUrl,
applied: applied ?? this.applied,
extensionNo: extensionNo??this.extensionNo,
employeeId: employeeId??this.employeeId,
name: name??this.name,
createdDate: createdDate??this.createdDate,
extensionNo: extensionNo ?? this.extensionNo,
employeeId: employeeId ?? this.employeeId,
name: name ?? this.name,
createdDate: createdDate ?? this.createdDate,
createdOn: createdOn ?? this.createdOn,
modifiedOn: modifiedOn ?? this.modifiedOn,
assetSerialNo: assetSerialNo ?? this.assetSerialNo,

@ -38,7 +38,12 @@ class GasRefillModel {
this.gazRefillDetails,
this.localEngineerSignature,
this.localNurseSignature,
this.timer});
this.timer,
this.timerModelList,
this.gasRefillTimer,
this.gasRefillAttachments,
});
GasRefillModel.fromJson(dynamic json) {
id = json['id'];
@ -55,6 +60,21 @@ class GasRefillModel {
employeeId = json['employeeId'];
name = json['name'];
createdDate = json['createdDate'];
//TODO need to use this when added from backend...
if (json['gasRefillTimer'] != null) {
gasRefillTimer = <GasRefillTimer>[];
json['gasRefillTimer'].forEach((v) {
gasRefillTimer?.add(GasRefillTimer.fromJson(v));
});
workingHours = json['gasRefillTimer'].fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item['endDateTime']).difference(DateTime.parse(item['startDateTime'])).inSeconds) ?? 0;
}
if (json['gasRefillAttachments'] != null) {
gasRefillAttachments = <GasRefillAttachments>[];
json['gasRefillAttachments'].forEach((v) {
gasRefillAttachments!.add(GasRefillAttachments.fromJson(v));
});
}
try {
final DateTime? sd = DateTime.tryParse(startDate ?? "");
final DateTime? st = DateTime.tryParse(startTime ?? "");
@ -98,7 +118,7 @@ class GasRefillModel {
String? endTime; // Now nullable
String? engSignature; // Now nullable
String? nurseSignature; // Now nullable
num? workingHours;
double? workingHours;
dynamic extensionNo;
String? employeeId;
String? name;
@ -113,56 +133,13 @@ class GasRefillModel {
List<GasRefillDetails>? gazRefillDetails; // Now nullable
Uint8List? localNurseSignature; // Now nullable
Uint8List? localEngineerSignature; // Now nullable
TimerModel? timer; // Now nullable
TimerModel? timer;
//TODO need to check when api provided..
List<TimerModel>? timerModelList = [];
List<GasRefillTimer>? gasRefillTimer = [];
List<GasRefillAttachments>? gasRefillAttachments;
GasRefillModel copyWith({
num? id, // Parameters are now nullable
String? gazRefillNo,
String? expectedDate,
String? expectedTime,
String? startDate,
String? startTime,
String? endDate,
String? endTime,
String? engSignature,
String? nurseSignature,
num? workingHours,
num? extensionNo,
num? employeeId,
String? name,
String? createdDate,
Site? site,
Building? building,
Floor? floor,
Department? department,
AssignedEmployee? assignedEmployee,
Lookup? status,
String? comment,
List<GasRefillDetails>? gazRefillDetails,
TimerModel? timer,
}) =>
GasRefillModel(
id: id ?? this.id,
gazRefillNo: gazRefillNo ?? this.gazRefillNo,
expectedDate: expectedDate ?? this.expectedDate,
expectedTime: expectedTime ?? this.expectedTime,
startDate: startDate ?? this.startDate,
startTime: startTime ?? this.startTime,
endDate: endDate ?? this.endDate,
endTime: endTime ?? this.endTime,
engSignature: engSignature ?? this.engSignature,
nurseSignature: nurseSignature ?? this.nurseSignature,
workingHours: workingHours ?? this.workingHours,
site: site ?? this.site,
building: building ?? this.building,
floor: floor ?? this.floor,
department: department ?? this.department,
assignedEmployee: assignedEmployee ?? this.assignedEmployee,
status: status ?? this.status,
comment: comment ?? this.comment,
gazRefillDetails: gazRefillDetails ?? this.gazRefillDetails,
timer: timer ?? this.timer,
);
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
@ -182,6 +159,14 @@ class GasRefillModel {
map['name'] = name;
map['createdDate'] = createdDate;
map['comment'] = comment;
//TODO need to check parameters here ...
if (gasRefillTimer != null) {
map['gasRefillTimer'] = gasRefillTimer?.map((v) => v.toJson()).toList();
}
if (gasRefillAttachments != null) {
map['gasRefillAttachments'] = gasRefillAttachments?.map((v) => v.toJson()).toList();
}
if (site != null) {
map['site'] = site?.toJson(addBuildings: false); // Use '?.' for null safety
}
@ -203,6 +188,8 @@ class GasRefillModel {
if (gazRefillDetails != null) {
map['gazRefillDetails'] = gazRefillDetails!.map((v) => v.toJson()).toList(); // Use '!' since gazRefillDetails could be null
}
return map;
}
@ -248,6 +235,58 @@ class GasRefillModel {
name = model.name;
createdDate = model.createdDate;
}
GasRefillModel copyWith({
num? id, // Parameters are now nullable
String? gazRefillNo,
String? expectedDate,
String? expectedTime,
String? startDate,
String? startTime,
String? endDate,
String? endTime,
String? engSignature,
String? nurseSignature,
double? workingHours,
num? extensionNo,
num? employeeId,
String? name,
String? createdDate,
Site? site,
Building? building,
Floor? floor,
Department? department,
AssignedEmployee? assignedEmployee,
Lookup? status,
String? comment,
List<GasRefillDetails>? gazRefillDetails,
List<GasRefillTimer>? gasRefillTimer,
TimerModel? timer,
}) =>
GasRefillModel(
id: id ?? this.id,
gazRefillNo: gazRefillNo ?? this.gazRefillNo,
expectedDate: expectedDate ?? this.expectedDate,
expectedTime: expectedTime ?? this.expectedTime,
startDate: startDate ?? this.startDate,
startTime: startTime ?? this.startTime,
endDate: endDate ?? this.endDate,
endTime: endTime ?? this.endTime,
engSignature: engSignature ?? this.engSignature,
nurseSignature: nurseSignature ?? this.nurseSignature,
workingHours: workingHours ?? this.workingHours,
site: site ?? this.site,
building: building ?? this.building,
floor: floor ?? this.floor,
department: department ?? this.department,
assignedEmployee: assignedEmployee ?? this.assignedEmployee,
status: status ?? this.status,
comment: comment ?? this.comment,
gazRefillDetails: gazRefillDetails ?? this.gazRefillDetails,
timer: timer ?? this.timer,
gasRefillTimer : gasRefillTimer ?? this.gasRefillTimer,
);
}
class GasRefillDetails {
@ -330,4 +369,51 @@ class GasRefillDetails {
}
return true;
}
}
class GasRefillTimer {
int? id;
String? startTime;
String? endTime;
dynamic workingHours;
GasRefillTimer({this.id, this.startTime, this.endTime, this.workingHours});
GasRefillTimer.fromJson(Map<String, dynamic> json) {
id = json['id'];
startTime = json['startDateTime'];
endTime = json['endDateTime'];
workingHours = json['workingHour'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['startDateTime'] = startTime;
data['endDateTime'] = endTime;
data['workingHour'] = workingHours;
return data;
}
}
class GasRefillAttachments {
int? id;
String? attachmentName;
GasRefillAttachments({this.id, this.attachmentName});
GasRefillAttachments.fromJson(Map<String, dynamic> json) {
id = json['id'];
attachmentName = json['attachmentName'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['attachmentName'] = attachmentName;
return data;
}
}

@ -949,14 +949,14 @@ class PreventiveVisitKits {
PreventiveVisitKits.fromJson(Map<String, dynamic> json) {
id = json['id'];
partCatalogItem = json['partCatalogItem'] != null ? PartCatalogItem.fromJson(json['partCatalogItem']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
if (partCatalogItem != null) {
// data['partCatalogItem'] = partCatalogItem!.toJson();
data['partCatalogItemId'] = partCatalogItem?.id;
}
return data;

@ -237,4 +237,6 @@ class _DeviceTransferDetailsState extends State<DeviceTransferDetails> {
}
}
}

@ -1,3 +1,335 @@
// import 'dart:convert';
// import 'dart:io';
//
// import 'package:flutter/foundation.dart';
// import 'package:flutter/material.dart';
// import 'package:fluttertoast/fluttertoast.dart';
// import 'package:provider/provider.dart';
// import 'package:test_sa/controllers/providers/api/asset_transfer_provider.dart';
// import 'package:test_sa/controllers/providers/api/user_provider.dart';
// import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
// import 'package:test_sa/extensions/context_extension.dart';
// import 'package:test_sa/extensions/int_extensions.dart';
// import 'package:test_sa/extensions/string_extensions.dart';
// import 'package:test_sa/extensions/widget_extensions.dart';
// import 'package:test_sa/models/device/asset_transfer.dart';
// import 'package:test_sa/models/device/asset_transfer_attachment.dart';
// import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
// import 'package:test_sa/providers/asset_transfer/asset_transfer_status_provider.dart';
// import 'package:test_sa/views/app_style/sizing.dart';
// import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
// import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
//
// import '../../../extensions/text_extensions.dart';
// import '../../../models/lookup.dart';
// import '../../../models/ppm/ppm.dart';
// import '../../../new_views/app_style/app_color.dart';
// import '../../../new_views/common_widgets/app_text_form_field.dart';
// import '../../../new_views/common_widgets/default_app_bar.dart';
// import '../../../new_views/common_widgets/single_item_drop_down_menu.dart';
// import '../../widgets/e_signature/e_signature.dart';
// import '../../widgets/timer/app_timer.dart';
//
// class UpdateDeviceTransfer extends StatefulWidget {
// final AssetTransfer model;
// final bool isSender;
//
// const UpdateDeviceTransfer({Key? key, required this.model, required this.isSender}) : super(key: key);
//
// @override
// State<UpdateDeviceTransfer> createState() => _UpdateDeviceTransferState();
// }
//
// class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
// final bool _isLoading = false;
// bool _validate = false;
// late UserProvider _userProvider;
// late SettingProvider _settingProvider;
// Uint8List? _signature;
// late AssetTransferProvider _deviceTransferProvider;
// final TextEditingController _requestedQuantityController = TextEditingController();
// final AssetTransfer _formModel = AssetTransfer();
// final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
// final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
//
// List<File> _files = [];
//
// _update() async {
// if (widget.isSender) {
// _formModel.senderVisitTimers?.add(
// VisitTimers(
// id: 0,
// startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(),
// endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(),
// workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60),
// ),
// );
// } else {
// _formModel.receiverVisitTimers?.add(
// VisitTimers(
// id: 0,
// startDateTime: _formModel.tbsTimer?.startAt?.toIso8601String(),
// endDateTime: _formModel.tbsTimer?.endAt?.toIso8601String(),
// workingHours: ((_formModel.tbsTimer?.durationInSecond ?? 0) / 60 / 60),
// ),
// );
// }
//
// if (_formModel.tbsTimer?.startAt == null) {
// await Fluttertoast.showToast(msg: "Working Hours Required");
// return false;
// }
// if (_formModel.tbsTimer?.endAt == null || isTimerRunning) {
// await Fluttertoast.showToast(msg: "Please Stop The Timer");
// return false;
// }
// _validate = true;
// if (!(_formKey.currentState!.validate())) {
// setState(() {});
// return false;
// }
// _formKey.currentState!.save();
//
// if (widget.isSender) {
// _formModel.senderAttachments = [];
// } else {
// _formModel.receiverAttachments = [];
// }
//
// try {
// for (var file in _files) {
// String attachmentName = file.path;
// if (attachmentName.contains("/")) {
// attachmentName = file.path.split("/").last;
// attachmentName = "$attachmentName|${base64Encode(file.readAsBytesSync())}";
// }
//
// if (widget.isSender) {
// _formModel.senderAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName));
// } else {
// _formModel.receiverAttachments!.add(AssetTransferAttachment(id: 0, attachmentName: attachmentName));
// }
// }
// } catch (error) {
// print(error);
// }
// await _deviceTransferProvider.updateRequest(context, assetTransfer: _formModel, isSender: widget.isSender);
// }
//
// @override
// void initState() {
// _formModel.fromDetails(widget.model);
//
// if (widget.isSender) {
// _files = widget.model.senderAttachments?.map((e) => File(e.attachmentName!)).toList() ?? [];
// } else {
// _files = widget.model.receiverAttachments?.map((e) => File(e.attachmentName!)).toList() ?? [];
// }
//
// super.initState();
// }
//
// @override
// void dispose() {
// _requestedQuantityController.dispose();
// super.dispose();
// }
//
// bool isTimerRunning = false;
//
// @override
// Widget build(BuildContext context) {
// _userProvider = Provider.of<UserProvider>(context);
// _settingProvider = Provider.of<SettingProvider>(context);
// _deviceTransferProvider = Provider.of<AssetTransferProvider>(context, listen: false);
//
// double totalWorkingHours = widget.isSender
// ? (widget.model.senderVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0)
// : (widget.model.receiverVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0);
//
// bool isTimerEnable = widget.isSender
// ? (!(_formModel.senderMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.senderMachineStatusName?.toLowerCase().contains("complete") ?? false))
// : (!(_formModel.receiverMachineStatusName?.toLowerCase().contains("close") ?? false) || !(_formModel.receiverMachineStatusName?.toLowerCase().contains("complete") ?? false));
//
// return Scaffold(
// appBar: DefaultAppBar(title: context.translation.updateRequest),
// key: _scaffoldKey,
// body: SafeArea(
// child: LoadingManager(
// isLoading: _isLoading,
// isFailedLoading: false,
// stateCode: 200,
// onRefresh: () async {},
// child: Form(
// key: _formKey,
// child: Column(
// children: [
// SingleChildScrollView(
// padding: EdgeInsets.all(12 * AppStyle.getScaleFactor(context)),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.stretch,
// children: [
// _buildCard(),
// 8.height,
// AppTextFormField(
// initialValue: widget.isSender ? _formModel.senderTravelingHours ?? "" : _formModel.receiverTravelingHours ?? "",
// labelText: context.translation.travelingHours,
// onChange: (text) {
// widget.isSender ? _formModel.senderTravelingHours = text : _formModel.receiverTravelingHours = text;
// },
// onSaved: (value) {
// widget.isSender ? _formModel.senderTravelingHours = value : _formModel.receiverTravelingHours = value;
// //_formModel?.workingHours = double.tryParse(value);
// // _formModel.travelingHours = value;
// },
// textInputType: TextInputType.number,
// //validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only",
// ),
// 8.height,
// if (totalWorkingHours > 0.0) ...[
// Container(
// height: 50.toScreenHeight,
// padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
// alignment: Alignment.centerLeft,
// decoration: BoxDecoration(
// color: context.isDark ? AppColor.neutral40 : AppColor.background(context),
// borderRadius: BorderRadius.circular(10),
// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
// ),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Text(
// "Total Working Time",
// style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500),
// ),
// Text(
// " ${formatDuration(totalWorkingHours.round())}",
// style: Theme.of(context).textTheme.bodyLarge,
// ),
// ],
// ),
// ),
// 8.height,
// ],
// AppTimer(
// label: context.translation.workingHours,
// timer: _formModel.tbsTimer,
// enabled: isTimerEnable,
// // enabled: widget.isSender ? _formModel.senderEndDate == null : (_formModel?.receiverMachineStatusName?.toLowerCase()?.contains("close") ?? false),
// timerProgress: (isRunning) {
// isTimerRunning = isRunning;
// },
// onChange: (timer) async {
// _formModel.tbsTimer = timer;
// return true;
// },
// ),
// 8.height,
// Consumer<AssetTransferStatusProvider>(builder: (context, snapshot, _) {
// return SingleItemDropDownMenu<Lookup, AssetTransferStatusProvider>(
// context: context,
// title: widget.isSender ? "Status Sender" : "Status Receiver", //,context.translation.reportStatus,
// initialValue:
// snapshot.items.firstWhere((element) => element.name == (widget.isSender ? _formModel.senderMachineStatusName : _formModel.receiverMachineStatusName), orElse: null),
// onSelect: (value) {
// if (value?.value == 4) {
// "Status cannot be change to ${value?.name}.".addTranslation.showToast;
// setState(() {});
// return;
// }
// if (widget.isSender) {
// _formModel.senderMachineStatusName = value?.name;
// _formModel.senderMachineStatusId = value?.id;
// } else {
// _formModel.receiverMachineStatusName = value?.name;
// _formModel.receiverMachineStatusId = value?.id;
// }
// setState(() {});
// },
// );
// }),
// 8.height,
// MultiFilesPicker(label: context.translation.attachImage, files: _files),
// 8.height,
// AppTextFormField(
// initialValue: widget.isSender ? _formModel.senderComment ?? "" : _formModel.receiverComment ?? "",
// labelText: context.translation.comments,
// textInputType: TextInputType.multiline,
// alignLabelWithHint: true,
// onSaved: (value) {
// widget.isSender ? _formModel.senderComment = value : _formModel.receiverComment = value;
// },
// ),
// 8.height,
// ESignature(
// title: "Signature",
// oldSignature: widget.isSender ? widget.model.senderEngSignature : widget.model.receiverEngSignature,
// newSignature: _signature,
// onSaved: (signature) {
// _signature = signature;
// if (signature == null || signature.isEmpty) return;
// widget.isSender
// ? _formModel.senderEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"
// : _formModel.receiverEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
// },
// ),
// ],
// ),
// ).expanded,
// Padding(
// padding: const EdgeInsets.all(16.0),
// child: AppFilledButton(
// label: context.translation.update,
// onPressed: _update,
// ),
// ),
// ],
// ),
// ),
// ),
// ),
// );
// }
//
// _buildCard() {
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// context.translation.transferDetails.heading5(context),
// 8.height,
// '${context.translation.assetName}: ${_formModel.assetName?.cleanupWhitespace.capitalizeFirstOfEach}'.bodyText(context),
// '${context.translation.requesterName}: ${_formModel.receiverEndUserName?.cleanupWhitespace.capitalizeFirstOfEach ?? ""}'.bodyText(context),
// ],
// ).toShadowContainer(context);
// }
//
// String formatDuration(int seconds) {
// int hours = seconds ~/ 3600;
// int minutes = (seconds % 3600) ~/ 60;
// int remainingSeconds = seconds % 60;
//
// String formattedDuration = '';
// if (hours > 0) {
// formattedDuration += '$hours hour${hours > 1 ? 's' : ''} ';
// }
// if (minutes > 0) {
// formattedDuration += '$minutes minute${minutes > 1 ? 's' : ''} ';
// }
// if (remainingSeconds > 0) {
// formattedDuration += '$remainingSeconds second${remainingSeconds > 1 ? 's' : ''} ';
// }
// if (formattedDuration.isEmpty) {
// formattedDuration = 'Less than a second';
// }
//
// return formattedDuration.trim();
// }
// }
//.....new design..
import 'dart:convert';
import 'dart:io';
@ -14,11 +346,18 @@ import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/device/asset_transfer.dart';
import 'package:test_sa/models/device/asset_transfer_attachment.dart';
import 'package:test_sa/models/new_models/work_order_detail_model.dart';
import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/providers/asset_transfer/asset_transfer_status_provider.dart';
import 'package:test_sa/service_request_latest/service_request_detail_provider.dart';
import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart';
import 'package:test_sa/service_request_latest/views/forms/maintenance_request/components/assistant_employee_card.dart';
import 'package:test_sa/views/app_style/sizing.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.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/status/report/service_report_assistant_employee_menu.dart';
import '../../../extensions/text_extensions.dart';
import '../../../models/lookup.dart';
@ -167,114 +506,132 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
SingleChildScrollView(
padding: EdgeInsets.all(12 * AppStyle.getScaleFactor(context)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildCard(),
8.height,
AppTextFormField(
initialValue: widget.isSender ? _formModel.senderTravelingHours ?? "" : _formModel.receiverTravelingHours ?? "",
labelText: context.translation.travelingHours,
onChange: (text) {
widget.isSender ? _formModel.senderTravelingHours = text : _formModel.receiverTravelingHours = text;
},
onSaved: (value) {
widget.isSender ? _formModel.senderTravelingHours = value : _formModel.receiverTravelingHours = value;
//_formModel?.workingHours = double.tryParse(value);
// _formModel.travelingHours = value;
},
textInputType: TextInputType.number,
//validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only",
),
8.height,
if (totalWorkingHours > 0.0) ...[
Container(
height: 50.toScreenHeight,
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
alignment: Alignment.centerLeft,
decoration: BoxDecoration(
color: context.isDark ? AppColor.neutral40 : AppColor.background(context),
borderRadius: BorderRadius.circular(10),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// _buildCard(),
// 8.height,
// AppTextFormField(
// initialValue: widget.isSender ? _formModel.senderTravelingHours ?? "" : _formModel.receiverTravelingHours ?? "",
// labelText: context.translation.travelingHours,
// onChange: (text) {
// widget.isSender ? _formModel.senderTravelingHours = text : _formModel.receiverTravelingHours = text;
// },
// onSaved: (value) {
// widget.isSender ? _formModel.senderTravelingHours = value : _formModel.receiverTravelingHours = value;
// //_formModel?.workingHours = double.tryParse(value);
// // _formModel.travelingHours = value;
// },
// textInputType: TextInputType.number,
// //validator: (value) => Validator.isNumeric(value) ? null : "allow numbers only",
// ),
// 8.height,
// if (totalWorkingHours > 0.0) ...[
// Container(
// height: 50.toScreenHeight,
// padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
// alignment: Alignment.centerLeft,
// decoration: BoxDecoration(
// color: context.isDark ? AppColor.neutral40 : AppColor.background(context),
// borderRadius: BorderRadius.circular(10),
// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)],
// ),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Text(
// "Total Working Time",
// style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500),
// ),
// Text(
// " ${formatDuration(totalWorkingHours.round())}",
// style: Theme.of(context).textTheme.bodyLarge,
// ),
// ],
// ),
// ),
// 8.height,
// ],
_timerWidget(context, totalWorkingHours, isTimerEnable),
8.height,
AppTextFormField(
initialValue: widget.isSender ? _formModel.senderComment ?? "" : _formModel.receiverComment ?? "",
labelText: context.translation.comments,
textInputType: TextInputType.multiline,
backgroundColor: AppColor.neutral100,
showShadow: false,
alignLabelWithHint: true,
onSaved: (value) {
widget.isSender ? _formModel.senderComment = value : _formModel.receiverComment = value;
},
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Total Working Time",
style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500),
),
Text(
" ${formatDuration(totalWorkingHours.round())}",
style: Theme.of(context).textTheme.bodyLarge,
),
],
// AppTimer(
// label: context.translation.workingHours,
// timer: _formModel.tbsTimer,
// enabled: isTimerEnable,
// // enabled: widget.isSender ? _formModel.senderEndDate == null : (_formModel?.receiverMachineStatusName?.toLowerCase()?.contains("close") ?? false),
// timerProgress: (isRunning) {
// isTimerRunning = isRunning;
// },
// onChange: (timer) async {
// _formModel.tbsTimer = timer;
// return true;
// },
// ),
// 8.height,
// Consumer<AssetTransferStatusProvider>(builder: (context, snapshot, _) {
// return SingleItemDropDownMenu<Lookup, AssetTransferStatusProvider>(
// context: context,
// title: widget.isSender ? "Status Sender" : "Status Receiver", //,context.translation.reportStatus,
// initialValue:snapshot.items.isNotEmpty?
// snapshot.items.firstWhere((element) => element.name == (widget.isSender ? _formModel.senderMachineStatusName : _formModel.receiverMachineStatusName), orElse: null):null,
// onSelect: (value) {
// if (value?.value == 4) {
// "Status cannot be change to ${value?.name}.".addTranslation.showToast;
// setState(() {});
// return;
// }
// if (widget.isSender) {
// _formModel.senderMachineStatusName = value?.name;
// _formModel.senderMachineStatusId = value?.id;
// } else {
// _formModel.receiverMachineStatusName = value?.name;
// _formModel.receiverMachineStatusId = value?.id;
// }
// setState(() {});
// },
// );
// }),
8.height,
MultiFilesPicker(
label: context.translation.attachFiles,
files: _files,
buttonColor: AppColor.black10,
onlyImages: false,
buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120),
),
),
8.height,
],
AppTimer(
label: context.translation.workingHours,
timer: _formModel.tbsTimer,
enabled: isTimerEnable,
// enabled: widget.isSender ? _formModel.senderEndDate == null : (_formModel?.receiverMachineStatusName?.toLowerCase()?.contains("close") ?? false),
timerProgress: (isRunning) {
isTimerRunning = isRunning;
},
onChange: (timer) async {
_formModel.tbsTimer = timer;
return true;
},
),
8.height,
Consumer<AssetTransferStatusProvider>(builder: (context, snapshot, _) {
return SingleItemDropDownMenu<Lookup, AssetTransferStatusProvider>(
context: context,
title: widget.isSender ? "Status Sender" : "Status Receiver", //,context.translation.reportStatus,
initialValue:
snapshot.items.firstWhere((element) => element.name == (widget.isSender ? _formModel.senderMachineStatusName : _formModel.receiverMachineStatusName), orElse: null),
onSelect: (value) {
if (value?.value == 4) {
"Status cannot be change to ${value?.name}.".addTranslation.showToast;
setState(() {});
return;
}
if (widget.isSender) {
_formModel.senderMachineStatusName = value?.name;
_formModel.senderMachineStatusId = value?.id;
} else {
_formModel.receiverMachineStatusName = value?.name;
_formModel.receiverMachineStatusId = value?.id;
}
setState(() {});
},
);
}),
8.height,
MultiFilesPicker(label: context.translation.attachImage, files: _files),
8.height,
AppTextFormField(
initialValue: widget.isSender ? _formModel.senderComment ?? "" : _formModel.receiverComment ?? "",
labelText: context.translation.comments,
textInputType: TextInputType.multiline,
alignLabelWithHint: true,
onSaved: (value) {
widget.isSender ? _formModel.senderComment = value : _formModel.receiverComment = value;
},
),
8.height,
ESignature(
title: "Signature",
oldSignature: widget.isSender ? widget.model.senderEngSignature : widget.model.receiverEngSignature,
newSignature: _signature,
onSaved: (signature) {
_signature = signature;
if (signature == null || signature.isEmpty) return;
widget.isSender
? _formModel.senderEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"
: _formModel.receiverEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
},
),
8.height,
// 8.height,
// ESignature(
// title: "Signature",
// oldSignature: widget.isSender ? widget.model.senderEngSignature : widget.model.receiverEngSignature,
// newSignature: _signature,
// onSaved: (signature) {
// _signature = signature;
// if (signature == null || signature.isEmpty) return;
// widget.isSender
// ? _formModel.senderEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}"
// : _formModel.receiverEngSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
// },
// ),
],
).toShadowContainer(context),
16.height,
const AssistantEmployeeCard().toShadowContainer(context, paddingObject: const EdgeInsets.symmetric(horizontal: 16)),
],
),
).expanded,
@ -293,6 +650,15 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
);
}
void updateTimer({TimerModel? timer}) {
_formModel.tbsTimer = timer;
if (timer?.startAt != null && timer?.endAt != null) {
_formModel.timerModelList = _formModel.timerModelList ?? [];
_formModel.timerModelList!.add(timer!);
}
// notifyListeners();
}
_buildCard() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -305,6 +671,44 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
).toShadowContainer(context);
}
Widget _timerWidget(BuildContext context, double totalWorkingHours, bool isTimerEnable) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
AppTimer(
label: context.translation.workingHours,
timer: _formModel.tbsTimer,
width: double.infinity,
enabled: isTimerEnable,
decoration: BoxDecoration(
color: AppColor.neutral100,
borderRadius: BorderRadius.circular(10),
),
timerProgress: (isRunning) {},
onChange: (timer) async {
updateTimer(timer: timer);
return true;
},
),
if (totalWorkingHours > 0.0) ...[
12.height,
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
'Total Working Time:'.bodyText2(context).custom(color: AppColor.neutral120),
8.width,
Text(
ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round()),
style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral50, fontWeight: FontWeight.w600),
),
],
),
],
],
);
}
String formatDuration(int seconds) {
int hours = seconds ~/ 3600;
int minutes = (seconds % 3600) ~/ 60;
@ -327,3 +731,226 @@ class _UpdateDeviceTransferState extends State<UpdateDeviceTransfer> {
return formattedDuration.trim();
}
}
class AssistantEmployeeCard extends StatefulWidget {
const AssistantEmployeeCard({super.key});
@override
State<AssistantEmployeeCard> createState() => _AssistantEmployeeCardState();
}
class _AssistantEmployeeCardState extends State<AssistantEmployeeCard> {
bool status = false;
final TextEditingController _workingHoursController = TextEditingController(text: '');
bool isCurrentUserIsAssistantEmp = false;
bool isExpanded = false;
@override
void initState() {
// TODO: implement initState
WidgetsBinding.instance.addPostFrameCallback((_) {
getInitialData();
});
super.initState();
}
Future<void> getInitialData() async {
final user = Provider.of<UserProvider>(context, listen: false).user!;
ServiceRequestDetailProvider requestDetailProvider = Provider.of<ServiceRequestDetailProvider>(context, listen: false);
isCurrentUserIsAssistantEmp = (user.userID != requestDetailProvider.currentWorkOrder?.data?.assignedEmployee?.userId);
// if (isCurrentUserIsAssistantEmp) {
// // _subWorkOrders.assistantEmployees = [widget.workOrder.assistantEmployees?.first?.copyWith(id: 0)];
// }
}
@override
void dispose() {
// TODO: implement dispose
_workingHoursController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Consumer<ServiceRequestDetailProvider>(builder: (context, requestDetailProvider, child) {
return Column(
children: [
SizedBox(
height: 56.toScreenHeight,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
context.translation.assistantEmployee.heading6(context).custom(color: AppColor.black10),
Icon(isExpanded ? Icons.keyboard_arrow_up_rounded : Icons.keyboard_arrow_down_rounded),
],
),
).onPress(() {
setState(() {
isExpanded = !isExpanded;
});
}),
isExpanded
? Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
ServiceReportAssistantEmployeeMenu(
title: context.translation.select,
backgroundColor: AppColor.neutral100,
// assetId: requestDetailProvider.currentWorkOrder!.data!.asset!.id!,
// initialValue: (requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployees?.isNotEmpty ?? false)
// ? requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployees?.first
// : null,
initialValue: null,
assetId: 23,
//TODO add check...
// enable: !isCurrentUserIsAssistantEmp,
onSelect: (employee) {
if (employee == null) {
requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployees = [];
} else {
requestDetailProvider.activityMaintenanceHelperModel?.assistantEmployees = [employee.copyWith(id: 0)];
requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.user = AssignedEmployee(userId: employee.user?.id, userName: employee.user?.name);
}
},
),
8.height,
Row(
mainAxisSize: MainAxisSize.min,
children: [
ADatePicker(
label: context.translation.startTime,
hideShadow: true,
backgroundColor: AppColor.neutral100,
date: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
).then((selectedTime) {
// Handle the selected date and time here.
if (selectedTime != null) {
DateTime selectedDateTime = DateTime(
selectedDate.year,
selectedDate.month,
selectedDate.day,
selectedTime.hour,
selectedTime.minute,
);
requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate = selectedDateTime;
requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
ServiceRequestUtils.calculateAndAssignWorkingHours(
startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate,
endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate,
workingHoursController: _workingHoursController,
updateModel: (hours) {
requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours = hours;
});
}
});
},
).expanded,
8.width,
ADatePicker(
label: context.translation.endTime,
hideShadow: true,
backgroundColor: AppColor.neutral100,
date: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate,
formatDateWithTime: true,
onDatePicker: (selectedDate) {
showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
).then((selectedTime) {
// Handle the selected date and time here.
if (selectedTime != null) {
DateTime selectedDateTime = DateTime(
selectedDate.year,
selectedDate.month,
selectedDate.day,
selectedTime.hour,
selectedTime.minute,
);
if (requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate != null &&
selectedDateTime.isBefore(requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.startDate!)) {
"End Date time must be greater then start date".showToast;
return;
}
requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate = selectedDateTime;
requestDetailProvider.updateActivityMaintenanceHelperModel(requestDetailProvider.activityMaintenanceHelperModel);
ServiceRequestUtils.calculateAndAssignWorkingHours(
startTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate,
endTime: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate,
workingHoursController: _workingHoursController,
updateModel: (hours) {
requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours = hours;
});
}
});
},
).expanded,
],
),
8.height,
AppTextFormField(
labelText: context.translation.workingHours,
backgroundColor: AppColor.neutral80,
controller: _workingHoursController,
suffixIcon: "clock".toSvgAsset(width: 20, color: context.isDark ? AppColor.neutral10 : null).paddingOnly(end: 16),
initialValue: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.workingHours != null
? requestDetailProvider.activityMaintenanceHelperModel!.modelAssistantEmployees!.workingHours.toString()
: '',
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
enable: false,
showShadow: false,
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
initialValue: requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment,
labelText: context.translation.technicalComment,
backgroundColor: AppColor.neutral100,
showShadow: false,
labelStyle: AppTextStyles.textFieldLabelStyle,
alignLabelWithHint: true,
textInputType: TextInputType.multiline,
onChange: (value) {
requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment = value;
},
onSaved: (value) {
requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.technicalComment = value;
},
),
16.height,
],
)
: const SizedBox(),
],
);
});
}
// //TODO move this to some common place....@waseem
// double calculateWorkingHours(DateTime? startTime, DateTime? endTime) {
// if (startTime != null && endTime != null) {
// Duration difference = endTime.difference(startTime);
// int hours = difference.inHours;
// int minutes = difference.inMinutes % 60;
// return hours.toDouble();
// } else {
// return -1;
// }
// }
//
// assignWorkingHours({required RequestDetailProvider requestDetailProvider}) {
// double hours = calculateWorkingHours(
// requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.startDate, requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.endDate);
// if (hours != -1) {
// _workingHoursController.text = hours.toString();
// requestDetailProvider.activityMaintenanceHelperModel?.modelAssistantEmployees?.workingHours = hours;
// }
// }
}

@ -7,6 +7,7 @@ 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/widget_extensions.dart';
import 'package:test_sa/views/pages/user/gas_refill/gas_refill_form.dart';
import 'package:test_sa/views/pages/user/gas_refill/request_gas_refill.dart';
import 'package:test_sa/views/widgets/loaders/app_loading.dart';
import 'package:test_sa/views/widgets/loaders/no_data_found.dart';
@ -143,7 +144,7 @@ class _GasRefillDetailsPageState extends State<GasRefillDetailsPage> {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RequestGasRefill(gasRefillModel: gasRefillModel),
builder: (context) => GasRefillForm(gasRefillModel: gasRefillModel),
),
).then((value) {
if (value != null) {
@ -239,3 +240,6 @@ class _GasRefillDetailsPageState extends State<GasRefillDetailsPage> {
}
}

@ -0,0 +1,424 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/api_routes/http_status_manger.dart';
import 'package:test_sa/controllers/providers/api/gas_refill_provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/controllers/validator/validator.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/widget_extensions.dart';
import 'package:test_sa/models/lookup.dart';
import 'package:test_sa/models/timer_model.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/providers/loading_list_notifier.dart';
import 'package:test_sa/service_request_latest/utilities/service_request_utils.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/loaders/loading_manager.dart';
import '../../../../controllers/providers/api/hospitals_provider.dart';
import '../../../../extensions/text_extensions.dart';
import '../../../../models/new_models/gas_refill_model.dart';
import '../../../../new_views/common_widgets/app_text_form_field.dart';
import '../../../../new_views/common_widgets/default_app_bar.dart';
import '../../../../new_views/common_widgets/single_item_drop_down_menu.dart';
import '../../../../providers/gas_request_providers/gas_status_provider.dart';
import '../../../widgets/e_signature/e_signature.dart';
import '../../../widgets/timer/app_timer.dart';
class GasRefillForm extends StatefulWidget {
static const String id = "/gas-refill-form";
final GasRefillModel? gasRefillModel;
const GasRefillForm({this.gasRefillModel, Key? key}) : super(key: key);
@override
State<GasRefillForm> createState() => _GasRefillFormState();
}
class _GasRefillFormState extends State<GasRefillForm> {
final bool _isLoading = false;
bool _validate = false;
Uint8List? _engineerSignature;
Uint8List? _nurseSignature;
double totalWorkingHours = 0.0;
late UserProvider _userProvider;
late SettingProvider _settingProvider;
GasRefillProvider? _gasRefillProvider;
GasRefillDetails _currentDetails = GasRefillDetails();
final TextEditingController _deliveredQuantityController = TextEditingController();
final TextEditingController _commentController = TextEditingController();
final TextEditingController _workingHoursController = TextEditingController();
final GasRefillModel _formModel = GasRefillModel(gazRefillDetails: []);
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey _DetailsKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
bool _firstTime = true;
Lookup? _deliveredQuantity;
static List<Lookup> deliveredQuantity = [
Lookup(name: "1", id: 1, value: 1),
Lookup(name: "2", id: 2, value: 2),
Lookup(name: "3", id: 3, value: 3),
Lookup(name: "4", id: 4, value: 4),
Lookup(name: "5", id: 5, value: 5)
];
@override
void initState() {
super.initState();
_gasRefillProvider ??= Provider.of<GasRefillProvider>(context, listen: false);
if (widget.gasRefillModel != null) {
_formModel.fromGasRefillModel(widget.gasRefillModel!);
// totalWorkingHours =
// _formModel?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0;
_commentController.text = _formModel.comment ?? "";
try {
_deliveredQuantity = deliveredQuantity.singleWhere((element) => element.value == _formModel.gazRefillDetails![0].deliverdQty);
_currentDetails.deliverdQty = _deliveredQuantity!.value;
} catch (ex) {}
}
if (_formModel.gasRefillAttachments != null && _formModel.gasRefillAttachments!.isNotEmpty) {
_gasRefillProvider?.gasRefillAttachments = [];
_gasRefillProvider?.gasRefillAttachments.addAll(_formModel.gasRefillAttachments!.map((e) => File(e.attachmentName!)).toList());
}
}
@override
void setState(VoidCallback fn) {
if (mounted) super.setState(() {});
}
_onSubmit(BuildContext context) async {
if (_formModel.status == null) {
await Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.status}");
return false;
}
if (_formModel.timer?.startAt == null) {
await Fluttertoast.showToast(msg: "Working Hours Required");
return false;
}
if (_formModel.timer?.endAt == null) {
await Fluttertoast.showToast(msg: "Please Stop The Timer");
return false;
}
if (_formModel.gazRefillDetails?.isNotEmpty ?? false) {
if (!(await _addNewModel(context))) return;
}
//TODO need to check when added in backend....
_formModel.gasRefillTimer = _formModel.gasRefillTimer ?? [];
_formModel.timerModelList?.forEach((timer) {
int durationInSecond = timer.endAt!.difference(timer.startAt!).inSeconds;
_formModel.gasRefillTimer?.add(
GasRefillTimer(
id: 0,
startTime: timer.startAt!.toIso8601String(), // Handle potential null
endTime: timer.endAt?.toIso8601String(), // Handle potential null
workingHours: ((durationInSecond) / 60 / 60),
),
);
});
_formModel.gasRefillAttachments = [];
for (var item in _gasRefillProvider!.gasRefillAttachments) {
_formModel.gasRefillAttachments
?.add(GasRefillAttachments(id: 0, attachmentName: ServiceRequestUtils.isLocalUrl(item.path) ? "${item.path.split("/").last}|${base64Encode(item.readAsBytesSync())}" : item.path));
}
//..till here...
setState(() {});
_formKey.currentState!.save();
_formModel.comment = _commentController.text;
int? status = widget.gasRefillModel == null
? 0 /*await _gasRefillProvider.createModel(
user: _userProvider.user,
model: _formModel,
)*/
: await _gasRefillProvider!.updateModel(
user: _userProvider.user!,
host: _settingProvider.host!,
oldModel: widget.gasRefillModel!,
newModel: _formModel,
);
//_isLoading = false;
setState(() {});
if (status >= 200 && status < 300) {
Fluttertoast.showToast(
msg: context.translation.successfulRequestMessage,
);
Navigator.of(context).pop(_formModel);
setState(() {});
} else {
String errorMessage = HttpStatusManger.getStatusMessage(status: status, subtitle: context.translation);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(errorMessage),
));
}
}
bool _addNewModel(BuildContext context) {
_validate = true;
if (_currentDetails.deliverdQty == null) {
Fluttertoast.showToast(msg: "${context.translation.youHaveToSelect} ${context.translation.quantity}");
setState(() {});
return false;
}
// if (!_formKey.currentState!.validate()) {
// setState(() {});
// return false;
// }
_formKey.currentState!.save();
_currentDetails.gasType = _formModel.gazRefillDetails![0].gasType;
_currentDetails.cylinderSize = _formModel.gazRefillDetails![0].cylinderSize;
_currentDetails.cylinderType = _formModel.gazRefillDetails![0].cylinderType;
_currentDetails.requestedQty = _formModel.gazRefillDetails![0].requestedQty;
if (!(_currentDetails.validate(context))) {
setState(() {});
return false;
}
_formModel.gazRefillDetails![0].deliverdQty = _currentDetails.deliverdQty;
_validate = false;
// Scrollable.ensureVisible(_DetailsKey.currentContext);
_deliveredQuantityController.clear();
_workingHoursController.clear();
//_commentController.clear();
_currentDetails = GasRefillDetails();
setState(() {});
return true;
}
@override
void dispose() {
_deliveredQuantityController.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);
_settingProvider = Provider.of<SettingProvider>(context);
if (_firstTime) {
String? clientName;
if (widget.gasRefillModel != null) {
//_formModel.status = widget.gasRefillModel?.status ?? Lookup(value: 0);
_gasRefillProvider!.expectedDateTime = DateTime.tryParse(_formModel.expectedDate ?? "");
_formModel.timer = TimerModel(startAt: DateTime.tryParse(widget.gasRefillModel?.startDate ?? ""), endAt: DateTime.tryParse(widget.gasRefillModel?.endDate ?? ""));
clientName = _formModel.site?.custName;
} else {
_formModel.timer = null;
clientName = _userProvider.user?.clientName;
}
HospitalsProvider().getHospitalsListByVal(searchVal: clientName ?? '').then((value) {
_gasRefillProvider!.hospital = value.firstWhere((element) => element.name == clientName, orElse: null);
_gasRefillProvider!.building = _gasRefillProvider!.hospital?.buildings?.firstWhere((element) => element.name == widget.gasRefillModel?.building?.name, orElse: null);
_gasRefillProvider!.floor = _gasRefillProvider!.building?.floors?.firstWhere((element) => element.name == widget.gasRefillModel?.floor?.name, orElse: null);
_gasRefillProvider!.department = _gasRefillProvider!.floor?.departments?.firstWhere((element) => element.name == widget.gasRefillModel?.department?.departmentName, orElse: null);
_firstTime = false;
setState(() {});
});
}
return Scaffold(
appBar: DefaultAppBar(title: context.translation.gasRefill),
key: _scaffoldKey,
body: Form(
key: _formKey,
child: SafeArea(
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: [
// Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// context.translation.gasRefill.heading5(context),
// 8.height,
// '${context.translation.gasRequest}: ${widget.gasRefillModel!.gazRefillDetails![0].gasType!.name}'.bodyText(context),
// '${context.translation.cylinderType}: ${widget.gasRefillModel!.gazRefillDetails![0].cylinderType!.name}'.bodyText(context),
// '${context.translation.cylinderSize}: ${widget.gasRefillModel!.gazRefillDetails![0].cylinderSize!.name}'.bodyText(context),
// '${context.translation.quantity}: ${widget.gasRefillModel!.gazRefillDetails![0].requestedQty ?? 0}'.bodyText(context),
// '${context.translation.site}: ${widget.gasRefillModel!.site?.name}'.bodyText(context),
// ],
// ).toShadowContainer(context),
8.height,
SingleItemDropDownMenu<Lookup, NullableLoadingProvider>(
context: context,
title: context.translation.quantity,
backgroundColor: AppColor.neutral100,
showShadow: false,
initialValue: _deliveredQuantity,
staticData: deliveredQuantity,
onSelect: (value) {
_deliveredQuantity = value;
_currentDetails.deliverdQty = value!.value;
},
),
8.height,
_timerWidget(context, _formModel.workingHours ?? 0),
8.height,
// SingleItemDropDownMenu<Lookup, GasStatusProvider>(
// context: context,
// title: context.translation.requestStatus,
// initialValue: _formModel.status,
// onSelect: (value) {
// if (value?.value == 0) {
// "Status cannot be change to ${value?.name}.".addTranslation.showToast;
// setState(() {});
// return;
// }
// if (value != null) {
// _formModel.status = value;
// }
// },
// ),
// 8.height,
// 8.height,
// AppTextFormField(
// initialValue: _formModel.gazRefillDetails?[0].deliverdQty?.toString() ?? "",
// labelText: context.translation.deliveredQuantity,
// onSaved: (value) {
// _currentDetails.deliverdQty = double.tryParse(value);
// },
// textInputType: TextInputType.number,
// controller: _deliveredQuantityController,
// validator: (value) => value == null || value.isEmpty
// ? context.translation.requiredField
// : Validator.isNumeric(value)
// ? null
// : context.translation.onlyNumbers,
// ),
8.height,
/// TBD
AppTextFormField(
labelText: context.translation.technicalComment,
textInputType: TextInputType.multiline,
alignLabelWithHint: true,
backgroundColor: AppColor.neutral100,
showShadow: false,
controller: _commentController,
onSaved: (value) {},
),
16.height,
MultiFilesPicker(
label: context.translation.attachFiles,
files: _gasRefillProvider!.gasRefillAttachments,
buttonColor: AppColor.black10,
onlyImages: false,
buttonIcon: 'image-plus'.toSvgAsset(color: AppColor.neutral120),
),
8.height,
// ESignature(
// title: "Engineer Signature",
// oldSignature: widget.gasRefillModel?.engSignature,
// newSignature: _engineerSignature,
// onSaved: (signature) {
// _engineerSignature = signature;
// if (signature == null || signature.isEmpty) return;
// _formModel.engSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
// //base64Encode(signature);
// },
// ),
// 8.height,
// ESignature(
// title: "Nurse Signature",
// oldSignature: widget.gasRefillModel?.nurseSignature,
// newSignature: _nurseSignature,
// onSaved: (signature) {
// _nurseSignature = signature;
// if (signature == null || signature.isEmpty) return;
// _formModel.nurseSignature = "${DateTime.now().toIso8601String()}.png|${base64Encode(signature)}";
// //base64Encode(signature);
// },
// ),
],
).toShadowContainer(context),
).expanded,
AppFilledButton(
label: widget.gasRefillModel == null ? context.translation.submit : context.translation.update,
onPressed: () async {
_onSubmit.call(context);
},
).paddingAll(16),
],
)),
),
),
);
}
Widget _timerWidget(BuildContext context, double totalWorkingHours) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
AppTimer(
label: context.translation.workingHours,
timer: _formModel.timer,
//TODO need to fix this..
// enabled: _formModel.endDate == null,
width: double.infinity,
decoration: BoxDecoration(
color: AppColor.neutral100,
borderRadius: BorderRadius.circular(10),
),
timerProgress: (isRunning) {},
onChange: (timer) async {
updateTimer(timer: timer);
return true;
},
),
if (totalWorkingHours > 0.0) ...[
12.height,
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
'Total Working Time:'.bodyText2(context).custom(color: AppColor.neutral120),
8.width,
Text(
ServiceRequestUtils.formatTimerDuration(totalWorkingHours.round()),
style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral50, fontWeight: FontWeight.w600),
),
],
),
],
],
);
}
}

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart';
@ -93,6 +95,7 @@ class _PpmPMKitsFormState extends State<PpmPMKitsForm> {
onPick: (part) {
model.partCatalogItem = PartCatalogItem(id: part.sparePart?.id, partNumber: part.sparePart?.partNo, partName: part.sparePart?.partName, oracleCode: part.sparePart?.oracleCode);
setState(() {});
print('part number i got is ${model.partCatalogItem?.partNumber}');
},
),
8.height,

@ -56,7 +56,6 @@ class _WoInfoFormState extends State<WoInfoForm> {
double totalWorkingHours =
widget.planPreventiveVisit.preventiveVisitTimers?.fold(0.0, (sum, item) => (sum ?? 0) + DateTime.parse(item.endDateTime!).difference(DateTime.parse(item.startDateTime!)).inSeconds) ?? 0;
totalWorkingHours = totalWorkingHours;
return Consumer<PpmProvider>(builder: (context, ppmProvider, child) {
return ListView(

@ -32,6 +32,7 @@ class _AutoCompletePartsFieldState extends State<AutoCompletePartsField> {
@override
void initState() {
print('initial value i got is ${widget.initialValue}');
_controller = TextEditingController(text: widget.initialValue);
super.initState();
}

Loading…
Cancel
Save