loan improvements

design_3.0_loan_module
Sikander Saleem 2 days ago
parent 35e494863f
commit 67da263e0d

@ -393,4 +393,5 @@ class URLs {
static get getLoanByWorkOrderId => '$_baseUrl/Loan/GetLoanByWorkOrderId'; static get getLoanByWorkOrderId => '$_baseUrl/Loan/GetLoanByWorkOrderId';
static get addLoan => '$_baseUrl/Loan/AddLoan'; static get addLoan => '$_baseUrl/Loan/AddLoan';
static get loanWorkflowAction => '$_baseUrl/Loan/LoanWorkflowAction';
} }

@ -7,6 +7,7 @@ class GenericAttachmentModel {
String? name; String? name;
String? createdBy; String? createdBy;
String? originalName; String? originalName;
GenericAttachmentModel.fromJson(Map<String, dynamic> json) { GenericAttachmentModel.fromJson(Map<String, dynamic> json) {
print('created by here is ${json['createdBy']}'); print('created by here is ${json['createdBy']}');
id = json['id']; id = json['id'];

@ -118,7 +118,9 @@ class LoanAttachments {
num? loanId; num? loanId;
String? attachmentName; String? attachmentName;
String? attachmentDescription; String? attachmentDescription;
LoanAttachments({this.id, this.loanAttachmentTypeId, this.attachmentName, this.loanId, this.attachmentDescription}); LoanAttachments({this.id, this.loanAttachmentTypeId, this.attachmentName, this.loanId, this.attachmentDescription});
LoanAttachments.fromJson(dynamic json) { LoanAttachments.fromJson(dynamic json) {
id = json['id']; id = json['id'];
loanAttachmentTypeId = json['loanAttachmentTypeId']; loanAttachmentTypeId = json['loanAttachmentTypeId'];

@ -13,6 +13,9 @@ class LoanInstallationPullOutFormModel {
DateTime? startTime; DateTime? startTime;
DateTime? endTime; DateTime? endTime;
double? totalHours; double? totalHours;
int? loanId;
String? userId;
int? loanStatusId;
LoanInstallationPullOutFormModel({ LoanInstallationPullOutFormModel({
this.loanAttachment, this.loanAttachment,
@ -23,18 +26,71 @@ class LoanInstallationPullOutFormModel {
this.startTime, this.startTime,
this.endTime, this.endTime,
this.totalHours, this.totalHours,
this.loanId,
this.loanStatusId,
this.userId,
}); });
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
//Need to check payload parm they need //Need to check payload parm they need
return { return {
'snNo': snNo, // 'snNo': snNo,
'InstallationDate': date?.toIso8601String(), 'serialNumber': snNo,
'installationDate': date?.toIso8601String(),
'pulloutDate': date?.toIso8601String(),
"loanAttachments": loanAttachment != null ? loanAttachment!.map((v) => v.toJson()).toList() : [], "loanAttachments": loanAttachment != null ? loanAttachment!.map((v) => v.toJson()).toList() : [],
"installationSignature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
"signature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null, "signature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
"pulloutSignature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
'startTime': startTime?.toIso8601String(), 'startTime': startTime?.toIso8601String(),
'endTime': endTime?.toIso8601String(), 'endTime': endTime?.toIso8601String(),
'totalHours': totalHours, 'totalHours': totalHours,
'loanId': loanId,
'loanStatusId': loanStatusId,
'userId': userId,
'isFromMobile': true,
};
}
Map<String, dynamic> toInstallationJson() {
//Need to check payload parm they need
return {
// 'snNo': snNo,
'serialNumber': snNo,
'installationDate': date?.toIso8601String(),
// 'pulloutDate': date?.toIso8601String(),
"loanAttachments": loanAttachment != null ? loanAttachment!.map((v) => v.toJson()).toList() : [],
"installationSignature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
// "signature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
// "pulloutSignature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
'startTime': startTime?.toIso8601String(),
'endTime': endTime?.toIso8601String(),
'totalHours': totalHours,
'loanId': loanId,
'loanStatusId': loanStatusId,
'userId': userId,
'isFromMobile': true,
};
}
Map<String, dynamic> toPulloutJson() {
//Need to check payload parm they need
return {
// 'snNo': snNo,
'serialNumber': snNo,
// 'installationDate': date?.toIso8601String(),
'pulloutDate': date?.toIso8601String(),
"loanAttachments": loanAttachment != null ? loanAttachment!.map((v) => v.toJson()).toList() : [],
// "installationSignature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
// "signature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
"pulloutSignature": signature != null ? "${DateTime.now().toIso8601String()}.png|${base64Encode(signature!)}" : null,
'startTime': startTime?.toIso8601String(),
'endTime': endTime?.toIso8601String(),
'totalHours': totalHours,
'loanId': loanId,
'loanStatusId': loanStatusId,
'userId': userId,
'isFromMobile': true,
}; };
} }
} }

@ -55,6 +55,8 @@ class LoanRequestModel {
int? pulloutWOItemId; int? pulloutWOItemId;
int? id; int? id;
String? installationDate; String? installationDate;
String? startTime;
String? endTime;
String? pulloutDate; String? pulloutDate;
String? createdBy; String? createdBy;
String? createdDate; String? createdDate;
@ -114,6 +116,8 @@ class LoanRequestModel {
this.id, this.id,
this.createdBy, this.createdBy,
this.installationDate, this.installationDate,
this.startTime,
this.endTime,
this.pulloutDate, this.pulloutDate,
this.createdDate, this.createdDate,
this.modifiedBy, this.modifiedBy,
@ -177,6 +181,8 @@ class LoanRequestModel {
pulloutWOItemId = json['pulloutWOItemId']; pulloutWOItemId = json['pulloutWOItemId'];
id = json['id']; id = json['id'];
installationDate = json['installationDate']; installationDate = json['installationDate'];
startTime = json['startTime'];
endTime = json['endTime'];
pulloutDate = json['pulloutDate']; pulloutDate = json['pulloutDate'];
createdBy = json['createdBy']; createdBy = json['createdBy'];
createdDate = json['createdDate']; createdDate = json['createdDate'];
@ -239,6 +245,8 @@ class LoanRequestModel {
data['pulloutWOItemId'] = this.pulloutWOItemId; data['pulloutWOItemId'] = this.pulloutWOItemId;
data['id'] = this.id; data['id'] = this.id;
data['installationDate'] = this.installationDate; data['installationDate'] = this.installationDate;
data['startTime'] = this.startTime;
data['endTime'] = this.endTime;
data['pulloutDate'] = this.pulloutDate; data['pulloutDate'] = this.pulloutDate;
data['createdBy'] = this.createdBy; data['createdBy'] = this.createdBy;
data['createdDate'] = this.createdDate; data['createdDate'] = this.createdDate;

@ -0,0 +1,223 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/helper/utils.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/cm_request_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/loan_module/models/loan_form_model.dart';
import 'package:test_sa/modules/loan_module/models/loan_installation_pullout_form_model.dart';
import 'package:test_sa/modules/loan_module/models/loan_request_model.dart';
import 'package:test_sa/modules/loan_module/provider/loan_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_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/views/widgets/date_and_time/date_picker.dart';
import 'package:test_sa/views/widgets/e_signature/e_signature.dart';
import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/timer/app_timer.dart';
class InstallationFormView extends StatefulWidget {
LoanRequestModel? loanData;
bool isInstallation;
InstallationFormView({Key? key, this.loanData, this.isInstallation = true}) : super(key: key);
@override
_InstallationFormViewState createState() {
return _InstallationFormViewState();
}
}
class _InstallationFormViewState extends State<InstallationFormView> {
final _formKey = GlobalKey<FormState>();
List<GenericAttachmentModel> _attachments = [];
final LoanInstallationPullOutFormModel _formData = LoanInstallationPullOutFormModel();
@override
void initState() {
super.initState();
_formData.loanId = widget.loanData?.id;
}
@override
void dispose() {
super.dispose();
}
void updateTimer({TimerModel? timer}) {
if (timer?.startAt != null && timer?.endAt != null) {
final start = timer!.startAt!;
final end = timer.endAt!;
final difference = end.difference(start);
final totalHours = difference.inSeconds / 3600.0;
_formData.startTime = start;
_formData.endTime = end;
_formData.totalHours = totalHours;
}
if (timer == null) {
_formData.startTime = null;
_formData.endTime = null;
_formData.totalHours = null;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: DefaultAppBar(title: 'Installation Report'.addTranslation),
body: Form(
key: _formKey,
child: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (widget.isInstallation) ...[
AppTextFormField(
initialValue: "",
labelText: "Updates SN",
validator: (value) {
if ((value ?? "").isEmpty) return "Mandatory";
return null;
},
style: Theme.of(context).textTheme.titleMedium,
backgroundColor: AppColor.fieldBgColor(context),
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
showShadow: false,
textInputType: TextInputType.text,
textInputAction: TextInputAction.next,
onChange: (value) {
_formData.snNo = value;
},
),
8.height,
],
ADatePicker(
label: widget.isInstallation ? "Installation Date".addTranslation : "Validation Date".addTranslation,
hideShadow: true,
backgroundColor: AppColor.fieldBgColor(context),
to: DateTime.now().add(const Duration(days: 365)),
formatDateWithTime: true,
date: _formData.date,
onDatePicker: (DateTime date) async {
final time = await showTimePicker(context: context, initialTime: TimeOfDay.now());
if (time == null) return;
setState(() {
_formData.date = DateTime(date.year, date.month, date.day, time.hour, time.minute);
});
},
),
8.height,
AppTimer(
label: context.translation.workingHours,
timer: _formData.timerModel,
// pickerFromDate: DateTime.tryParse(widget.createdDate ?? ''),
pickerFromDate: DateTime(DateTime.now().year, DateTime.now().month, 1),
pickerTimer: _formData.timerModel,
showTimer: false,
onPick: (timer) {
updateTimer(timer: timer);
},
width: double.infinity,
decoration: BoxDecoration(
color: AppColor.fieldBgColor(context),
borderRadius: BorderRadius.circular(10),
),
timerProgress: (isRunning) {},
onChange: (timer) async {
updateTimer(timer: timer);
return true;
},
),
ESignature(
title: 'End-user signature'.addTranslation,
backgroundColor: AppColor.fieldBgColor(context),
showShadow: false,
oldSignature: '',
newSignature: _formData.signature,
onChange: (Uint8List signature) {
if (signature.isEmpty) return;
setState(() {
_formData.signature = signature;
});
},
),
24.height,
"Attachments".bodyText(context).custom(color: AppColor.black10),
8.height,
AttachmentPicker(
label: context.translation.attachments,
attachment: _attachments,
buttonColor: AppColor.primary10,
onlyImages: false,
showAsListView: true,
buttonIcon: 'attachment_icon'.toSvgAsset(color: AppColor.primary10),
onChange: (attachments) {
_attachments = attachments;
setState(() {});
},
),
],
).toShadowContainer(context, borderRadius: 20),
).expanded,
FooterActionButton.footerContainer(
context: context,
child: AppFilledButton(
buttonColor: AppColor.primary10,
label: context.translation.submitRequest,
onPressed: _submitForm,
),
),
],
),
),
);
}
Future<void> _submitForm() async {
if (!_formKey.currentState!.validate()) return;
if (_formData.date == null) {
"Please select installation date".showToast;
return;
}
if (_formData.startTime == null || _formData.endTime == null) {
"Please select start and end time".showToast;
return;
}
if (_formData.signature == null || _formData.signature!.isEmpty) {
"Signature is required".showToast;
return;
}
_formData.loanAttachment = [];
for (var item in _attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
_formData.loanAttachment!.add(LoanAttachments(id: 0, attachmentName: fileName, loanId: widget.loanData?.id));
}
Utils.showLoading(context);
_formData.loanStatusId = widget.loanData?.loanStatusValue;
_formData.userId = context.userProvider.user?.userID;
LoanProvider incidentProvider = Provider.of<LoanProvider>(context, listen: false);
bool isSuccess = await incidentProvider.loanWorkflowAction(_formData.toInstallationJson());
Utils.hideLoading(context);
if (isSuccess) {
Navigator.pop(context, true);
}
}
}

@ -1,16 +1,24 @@
import 'dart:convert';
import 'dart:developer'; import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/helper/utils.dart';
import 'package:test_sa/models/generic_attachment_model.dart'; import 'package:test_sa/models/generic_attachment_model.dart';
import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/models/timer_model.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart'; import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/loan_module/models/loan_form_model.dart';
import 'package:test_sa/modules/loan_module/models/loan_installation_pullout_form_model.dart'; import 'package:test_sa/modules/loan_module/models/loan_installation_pullout_form_model.dart';
import 'package:test_sa/modules/loan_module/models/loan_request_model.dart';
import 'package:test_sa/modules/loan_module/provider/loan_provider.dart';
import 'package:test_sa/new_views/app_style/app_color.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_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart'; import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
@ -21,10 +29,10 @@ import 'package:test_sa/views/widgets/images/multi_image_picker.dart';
import 'package:test_sa/views/widgets/timer/app_timer.dart'; import 'package:test_sa/views/widgets/timer/app_timer.dart';
class InstallationPullOutFormView extends StatefulWidget { class InstallationPullOutFormView extends StatefulWidget {
final bool isPullout;
final String? createdDate; final String? createdDate;
final LoanRequestModel? loanData;
const InstallationPullOutFormView({super.key, required this.isPullout, this.createdDate}); const InstallationPullOutFormView({super.key, this.createdDate, this.loanData});
@override @override
State<InstallationPullOutFormView> createState() => _InstallationPullOutFormViewState(); State<InstallationPullOutFormView> createState() => _InstallationPullOutFormViewState();
@ -34,7 +42,16 @@ class _InstallationPullOutFormViewState extends State<InstallationPullOutFormVie
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
final _snController = TextEditingController(); final _snController = TextEditingController();
List<GenericAttachmentModel> _attachments = []; List<GenericAttachmentModel> _attachments = [];
final _formData = LoanInstallationPullOutFormModel(); final LoanInstallationPullOutFormModel _formData = LoanInstallationPullOutFormModel();
@override
void initState() {
// TODO: implement initState
super.initState();
_formData.loanId = widget.loanData?.id;
_formData.loanStatusId = widget.loanData?.loanStatusValue;
_formData.userId = context.userProvider.user?.userID;
}
@override @override
void dispose() { void dispose() {
@ -66,23 +83,6 @@ class _InstallationPullOutFormViewState extends State<InstallationPullOutFormVie
}); });
} }
void _submitForm() {
if (!_formKey.currentState!.validate()) return;
//Validation if required .
// if (_formData.date == null) {
// context.showSnackBar('Please select installation date');
// return;
// }
//
// if (_formData.signature == null || _formData.signature!.isEmpty) {
// context.showSnackBar('Signature is required');
// return;
// }
_formData.snNo = _snController.text;
}
void updateTimer({TimerModel? timer}) { void updateTimer({TimerModel? timer}) {
if (timer?.startAt != null && timer?.endAt != null) { if (timer?.startAt != null && timer?.endAt != null) {
final start = timer!.startAt!; final start = timer!.startAt!;
@ -98,9 +98,8 @@ class _InstallationPullOutFormViewState extends State<InstallationPullOutFormVie
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: widget.isPullout ? null : DefaultAppBar(title: 'Installation Report'.addTranslation), // appBar: DefaultAppBar(title: 'Pullout Report'.addTranslation),
body: SafeArea( body: Form(
child: Form(
key: _formKey, key: _formKey,
child: Column( child: Column(
children: [ children: [
@ -109,29 +108,29 @@ class _InstallationPullOutFormViewState extends State<InstallationPullOutFormVie
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
if (!widget.isPullout) ...[
AppTextFormField(
controller: _snController,
labelText: context.translation.snNo,
backgroundColor: AppColor.fieldBgColor(context),
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
hintStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.text,
textInputAction: TextInputAction.next,
showShadow: false,
validator: (v) => (v == null || v.isEmpty) ? 'Required' : null,
),
8.height,
],
ADatePicker( ADatePicker(
label: !widget.isPullout ? "Installation Date".addTranslation : "Validation Date".addTranslation, label: "Validation Date".addTranslation,
hideShadow: true, hideShadow: true,
backgroundColor: AppColor.fieldBgColor(context), backgroundColor: AppColor.fieldBgColor(context),
to: DateTime.now().add(const Duration(days: 365)), to: DateTime.now().add(const Duration(days: 365)),
formatDateWithTime: true, formatDateWithTime: true,
onDatePicker: _pickInstallationDate, date: _formData.date,
onDatePicker: (DateTime date) async {
final time = await showTimePicker(context: context, initialTime: TimeOfDay.now());
if (time == null) return;
setState(() {
_formData.date = DateTime(date.year, date.month, date.day, time.hour, time.minute);
});
},
), ),
// ADatePicker(
// label: !widget.isPullout ? "Installation Date".addTranslation : "Validation Date".addTranslation,
// hideShadow: true,
// backgroundColor: AppColor.fieldBgColor(context),
// to: DateTime.now().add(const Duration(days: 365)),
// formatDateWithTime: true,
// onDatePicker: _pickInstallationDate,
// ),
8.height, 8.height,
AppTimer( AppTimer(
label: context.translation.workingHours, label: context.translation.workingHours,
@ -163,10 +162,24 @@ class _InstallationPullOutFormViewState extends State<InstallationPullOutFormVie
onChange: _onSignatureChanged, onChange: _onSignatureChanged,
), ),
24.height, 24.height,
"Attachments".bodyText(context).custom(color: AppColor.black10),
8.height,
AttachmentPicker( AttachmentPicker(
label: context.translation.attachments, label: context.translation.attachments,
attachment: _attachments, attachment: _attachments,
buttonColor: AppColor.primary10,
onlyImages: false,
showAsListView: true,
buttonIcon: 'attachment_icon'.toSvgAsset(color: AppColor.primary10),
onChange: (attachments) {
_attachments = attachments;
setState(() {});
},
), ),
// AttachmentPicker(
// label: context.translation.attachments,
// attachment: _attachments,
// ),
], ],
).toShadowContainer(context, borderRadius: 20), ).toShadowContainer(context, borderRadius: 20),
).expanded, ).expanded,
@ -181,7 +194,36 @@ class _InstallationPullOutFormViewState extends State<InstallationPullOutFormVie
], ],
), ),
), ),
),
); );
} }
Future<void> _submitForm() async {
if (!_formKey.currentState!.validate()) return;
if (_formData.date == null) {
"Please select Validation date".showToast;
return;
}
if (_formData.startTime == null || _formData.endTime == null) {
"Please select start and end time".showToast;
return;
}
if (_formData.signature == null || _formData.signature!.isEmpty) {
"Signature is required".showToast;
return;
}
_formData.loanAttachment = [];
for (var item in _attachments) {
String fileName = CMRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
_formData.loanAttachment!.add(LoanAttachments(id: 0, attachmentName: fileName, loanId: widget.loanData?.id));
}
Utils.showLoading(context);
LoanProvider incidentProvider = Provider.of<LoanProvider>(context, listen: false);
bool isSuccess = await incidentProvider.loanWorkflowAction(_formData.toPulloutJson());
Utils.hideLoading(context);
if (isSuccess) {
Navigator.pop(context, true);
}
}
} }

@ -1,10 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:test_sa/controllers/api_routes/urls.dart'; import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart'; import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/cm_module/cm_request_utils.dart';
import 'package:test_sa/modules/loan_module/models/loan_request_model.dart'; import 'package:test_sa/modules/loan_module/models/loan_request_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/views/widgets/images/files_list.dart'; import 'package:test_sa/views/widgets/images/files_list.dart';
@ -16,72 +18,76 @@ class InstallationDetailsView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
String workingTime = "-";
if (loanData.startTime != null && loanData.endTime != null) {
try {
final timeFormat = DateFormat('h:mm a'); // Matches "3:00 PM" format
final now = DateTime.now();
final start = timeFormat.parse(loanData.startTime!);
var end = timeFormat.parse(loanData.endTime!);
// Set the date to today for both times
var startDateTime = DateTime(now.year, now.month, now.day, start.hour, start.minute);
var endDateTime = DateTime(now.year, now.month, now.day, end.hour, end.minute);
// If end time is before start time, shift crossed midnight
if (endDateTime.isBefore(startDateTime)) {
endDateTime = endDateTime.add(const Duration(days: 1));
}
double totalWorkingTime = endDateTime.difference(startDateTime).inSeconds / 3600.0;
} catch (ex) {}
}
// if (loanData.startTime != null && loanData.endTime != null) {
// final start = DateTime.parse(loanData.startTime!);
// var end = DateTime.parse(loanData.endTime!);
//
// // If end time is before start time, it means the shift crossed midnight
// if (end.isBefore(start)) {
// end = end.add(const Duration(days: 1));
// }
//
// double totalWorkingTime = end.difference(start).inSeconds / 3600.0;
// workingTime = CMRequestUtils.formatTotalWorkingHours(totalWorkingTime);
// }
// if (loanData.startTime != null && loanData.endTime != null) {
// final start = DateTime.parse(loanData.startTime!);
// final end = DateTime.parse(loanData.endTime!);
// double totalWorkingTime = end.difference(start).inSeconds / 3600.0;
// workingTime = CMRequestUtils.formatTotalWorkingHours(totalWorkingTime);
// }
return Padding( return Padding(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( Text(
mainAxisAlignment: MainAxisAlignment.spaceBetween, "Installation Details".addTranslation,
children: [ style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
detailContent(
context: context,
heading: 'Updates SN:',
label: loanData.installationDate??'-'
),
detailContent(
context: context,
heading: 'Installation Date',
label: loanData.installationDate??'-'
),
],
),
12.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
detailContent(
context: context,
heading: 'Start Time',
label: loanData.installationDate??'-'
),
detailContent(
context: context,
heading: 'End Time',
label: loanData.installationDate??'-'
),
],
),
12.height,
detailContent(
context: context,
heading: 'Total Time',
label: loanData.installationDate??'-'
), ),
4.height,
'Updates SN: ${loanData.assetSerialNumber ?? "-"}'.bodyText(context),
'Installation Date: ${loanData.installationDate?.toAssetDetailsFormat ?? "-"}'.bodyText(context),
'Start Time: ${loanData.startTime ?? "-"}'.bodyText(context),
'End Time: ${loanData.endTime ?? "-"}'.bodyText(context),
'Total Working Time: $workingTime'.bodyText(context),
if (loanData.loanAttachments!.isNotEmpty) ...[ if (loanData.loanAttachments!.isNotEmpty) ...[
12.height, 12.height,
Text( Text(
"Uploads Phase 2 docs".addTranslation, "Uploads Phase 2 docs".addTranslation,
style: AppTextStyles.bodyText.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
), ),
8.height, 8.height,
FilesList(images: loanData.loanAttachments?.map((e) => URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList() ?? []), FilesList(showAsListView: true, images: loanData.loanAttachments?.map((e) => URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList() ?? []),
], ],
], ],
).toShadowContainer(context, borderRadius: 20), ).toShadowContainer(context, borderRadius: 20),
); );
} }
Widget detailContent({required BuildContext context, required String label, required String heading}) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
heading.bodyText(context).custom(color: AppColor.neutral120),
6.height,
//TODO Need to check which value need to show here
label.bodyText(context).custom(color: AppColor.neutral120),
],
);
}
} }

@ -8,6 +8,7 @@ import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_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/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/modules/loan_module/models/loan_attachment_model.dart'; import 'package:test_sa/modules/loan_module/models/loan_attachment_model.dart';
import 'package:test_sa/modules/loan_module/pages/installation_form_view.dart';
import 'package:test_sa/modules/loan_module/pages/pullout_detail_page.dart'; import 'package:test_sa/modules/loan_module/pages/pullout_detail_page.dart';
import 'package:test_sa/modules/loan_module/provider/loan_provider.dart'; import 'package:test_sa/modules/loan_module/provider/loan_provider.dart';
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
@ -20,19 +21,35 @@ import 'package:test_sa/views/widgets/requests/request_status.dart';
import '../models/loan_request_model.dart'; import '../models/loan_request_model.dart';
import 'installation_pullout_form_view.dart'; import 'installation_pullout_form_view.dart';
class LoanEquipmentDetailPage extends StatelessWidget { class LoanEquipmentDetailPage extends StatefulWidget {
static const String id = "/loan-equipment-detail-page"; static const String id = "/loan-equipment-detail-page";
final int loanId; final int loanId;
LoanEquipmentDetailPage({Key? key, required this.loanId}) : super(key: key); LoanEquipmentDetailPage({Key? key, required this.loanId}) : super(key: key);
@override
_LoanEquipmentDetailPageState createState() {
return _LoanEquipmentDetailPageState();
}
}
class _LoanEquipmentDetailPageState extends State<LoanEquipmentDetailPage> {
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: const DefaultAppBar(title: "Request Details"), appBar: const DefaultAppBar(title: "Request Details"),
body: SafeArea( body: FutureBuilder<LoanRequestModel?>(
child: FutureBuilder<LoanRequestModel?>( future: Provider.of<LoanProvider>(context, listen: false).getLoanById(widget.loanId),
future: Provider.of<LoanProvider>(context, listen: false).getLoanById(loanId),
builder: (BuildContext context, AsyncSnapshot<LoanRequestModel?> snapshot) { builder: (BuildContext context, AsyncSnapshot<LoanRequestModel?> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) return const CircularProgressIndicator(color: AppColor.primary10).center; if (snapshot.connectionState == ConnectionState.waiting) return const CircularProgressIndicator(color: AppColor.primary10).center;
if (snapshot.data == null) return const NoDataFound().center; if (snapshot.data == null) return const NoDataFound().center;
@ -65,21 +82,21 @@ class LoanEquipmentDetailPage extends StatelessWidget {
), ),
12.height, 12.height,
...requesterDetails(context, snapshot.data!), ...requesterDetails(context, snapshot.data!),
12.height, const Divider().defaultStyle(context),
...requestDetails(context, snapshot.data!), ...requestDetails(context, snapshot.data!),
12.height, const Divider().defaultStyle(context),
...assetDetails(context, snapshot.data!), ...assetDetails(context, snapshot.data!),
12.height, const Divider().defaultStyle(context),
...installationDetails(context, snapshot.data!), ...installationDetails(context, snapshot.data!),
12.height, const Divider().defaultStyle(context),
...doctorDetails(context, snapshot.data!), ...doctorDetails(context, snapshot.data!),
12.height, const Divider().defaultStyle(context),
...vendorDetails(context, snapshot.data!), ...vendorDetails(context, snapshot.data!),
if (allAttachments.isNotEmpty) ...[ if (allAttachments.isNotEmpty) ...[
const Divider().defaultStyle(context), const Divider().defaultStyle(context),
Text( Text(
"Attachments".addTranslation, "Attachments".addTranslation,
style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
), ),
FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList() ?? []), FilesList(images: allAttachments.map((e) => URLs.getFileUrl(e.attachmentName ?? '') ?? '').toList() ?? []),
], ],
@ -87,34 +104,35 @@ class LoanEquipmentDetailPage extends StatelessWidget {
).toShadowContainer(context, padding: 12), ).toShadowContainer(context, padding: 12),
], ],
).expanded, ).expanded,
// if (context.userProvider.isEngineer && (snapshot.data?.loanStatusValue == 5 || snapshot.data?.loanStatusValue == 8)) // @todo ask backend to add loanTypeValue, so we can show or hide the buttons
// FooterActionButton.footerContainer( if (snapshot.data?.loanTypeName == "Standard" && context.userProvider.isEngineer && (snapshot.data?.loanStatusValue == 5 || snapshot.data?.loanStatusValue == 8))
// context: context, FooterActionButton.footerContainer(
// child: AppFilledButton( context: context,
// onPressed: () async { child: AppFilledButton(
// if (snapshot.data?.loanStatusValue == 5) { onPressed: () async {
// Navigator.push( if (snapshot.data?.loanStatusValue == 5) {
// context, bool isSuccess = await Navigator.push(context, MaterialPageRoute(builder: (context) => InstallationFormView(loanData: snapshot.data))) ?? false;
// MaterialPageRoute( if (isSuccess) {
// builder: (context) => PullOutDetailsPage( setState(() {});
// loanData: snapshot.data, }
// ))); return;
// return; }
// } bool isSuccess = await Navigator.push(context, MaterialPageRoute(builder: (context) => PullOutDetailsPage(loanData: snapshot.data))) ?? false;
// Navigator.push(context, MaterialPageRoute(builder: (context) => const InstallationPullOutFormView(isPullout: false))); if (isSuccess) {
// }, setState(() {});
// label: snapshot.data?.loanStatusValue == 5 ? 'Installation Report' : 'PullOut Report', }
// ), },
// ) label: snapshot.data?.loanStatusValue == 5 ? 'Installation Report' : 'PullOut Report',
),
)
], ],
); );
}), }));
));
} }
List<Widget> requestDetails(BuildContext context, LoanRequestModel loanData) { List<Widget> requestDetails(BuildContext context, LoanRequestModel loanData) {
return [ return [
Text("Request Details", style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)), Text("Request Details", style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)),
'Loan Type: ${loanData.loanTypeName ?? "-"}'.bodyText(context), 'Loan Type: ${loanData.loanTypeName ?? "-"}'.bodyText(context),
'Loan No: ${loanData.reqCode ?? "-"}'.bodyText(context), 'Loan No: ${loanData.reqCode ?? "-"}'.bodyText(context),
'Loan Period: ${loanData.loanPeriodName ?? "-"}'.bodyText(context), 'Loan Period: ${loanData.loanPeriodName ?? "-"}'.bodyText(context),
@ -127,7 +145,7 @@ class LoanEquipmentDetailPage extends StatelessWidget {
List<Widget> vendorDetails(BuildContext context, LoanRequestModel loanData) { List<Widget> vendorDetails(BuildContext context, LoanRequestModel loanData) {
return [ return [
Text("Vendor Information", style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)), Text("Vendor Information", style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)),
'Name: ${loanData.vendorName ?? "-"}'.bodyText(context), 'Name: ${loanData.vendorName ?? "-"}'.bodyText(context),
'Representative Name: ${loanData.vendorRepName ?? "-"}'.bodyText(context), 'Representative Name: ${loanData.vendorRepName ?? "-"}'.bodyText(context),
'Contact: ${loanData.vendorContact ?? "-"}'.bodyText(context), 'Contact: ${loanData.vendorContact ?? "-"}'.bodyText(context),
@ -137,7 +155,7 @@ class LoanEquipmentDetailPage extends StatelessWidget {
List<Widget> assetDetails(BuildContext context, LoanRequestModel loanData) { List<Widget> assetDetails(BuildContext context, LoanRequestModel loanData) {
return [ return [
Text("Asset Information", style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)), Text("Asset Information", style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)),
'${context.translation.assetName}: ${loanData.assetName ?? "-"}'.bodyText(context), '${context.translation.assetName}: ${loanData.assetName ?? "-"}'.bodyText(context),
'${context.translation.assetNo}: ${loanData.assetNumber ?? "-"}'.bodyText(context), '${context.translation.assetNo}: ${loanData.assetNumber ?? "-"}'.bodyText(context),
'${context.translation.serialNumber}: ${loanData.assetSerialNumber ?? "-"}'.bodyText(context), '${context.translation.serialNumber}: ${loanData.assetSerialNumber ?? "-"}'.bodyText(context),
@ -148,7 +166,7 @@ class LoanEquipmentDetailPage extends StatelessWidget {
List<Widget> installationDetails(BuildContext context, LoanRequestModel loanData) { List<Widget> installationDetails(BuildContext context, LoanRequestModel loanData) {
return [ return [
Text("Installation & Pullout Information", style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)), Text("Installation & Pullout Information", style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)),
'Installation EDD: ${loanData.installationEDD?.toServiceRequestDetailsFormat ?? "-"}'.bodyText(context), 'Installation EDD: ${loanData.installationEDD?.toServiceRequestDetailsFormat ?? "-"}'.bodyText(context),
'Installation Date: ${loanData.installationEDD?.toAssetDetailsFormat ?? "-"}'.bodyText(context), 'Installation Date: ${loanData.installationEDD?.toAssetDetailsFormat ?? "-"}'.bodyText(context),
'Pullout EDD: ${loanData.pulloutEDD?.toServiceRequestDetailsFormat ?? "-"}'.bodyText(context), 'Pullout EDD: ${loanData.pulloutEDD?.toServiceRequestDetailsFormat ?? "-"}'.bodyText(context),
@ -158,7 +176,7 @@ class LoanEquipmentDetailPage extends StatelessWidget {
List<Widget> doctorDetails(BuildContext context, LoanRequestModel loanData) { List<Widget> doctorDetails(BuildContext context, LoanRequestModel loanData) {
return [ return [
Text("Doctor Information", style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)), Text("Doctor Information", style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)),
'Name: ${loanData.doctorName ?? "-"}'.bodyText(context), 'Name: ${loanData.doctorName ?? "-"}'.bodyText(context),
'Contact: ${loanData.doctorContact ?? "-"}'.bodyText(context), 'Contact: ${loanData.doctorContact ?? "-"}'.bodyText(context),
'Email: ${loanData.doctorEmail ?? "-"}'.bodyText(context), 'Email: ${loanData.doctorEmail ?? "-"}'.bodyText(context),
@ -167,7 +185,7 @@ class LoanEquipmentDetailPage extends StatelessWidget {
List<Widget> requesterDetails(BuildContext context, LoanRequestModel loanData) { List<Widget> requesterDetails(BuildContext context, LoanRequestModel loanData) {
return [ return [
Text("Requester Information", style: AppTextStyles.heading4.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)), Text("Requester Information", style: AppTextStyles.heading6.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50)),
'Name: ${loanData.requestorUserIdForDisplay ?? "-"}'.bodyText(context), 'Name: ${loanData.requestorUserIdForDisplay ?? "-"}'.bodyText(context),
'Email: ${loanData.requestorUserEmail ?? "-"}'.bodyText(context), 'Email: ${loanData.requestorUserEmail ?? "-"}'.bodyText(context),
'Contact: ${loanData.requestorUserMobileNumber ?? "-"}'.bodyText(context), 'Contact: ${loanData.requestorUserMobileNumber ?? "-"}'.bodyText(context),

@ -10,29 +10,17 @@ import 'package:test_sa/modules/loan_module/pages/intallation_details_view.dart'
import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart'; import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
class PullOutDetailsPage extends StatefulWidget { class PullOutDetailsPage extends StatelessWidget {
final LoanRequestModel? loanData; final LoanRequestModel? loanData;
PullOutDetailsPage({Key? key, required this.loanData}) : super(key: key); PullOutDetailsPage({Key? key, required this.loanData}) : super(key: key);
@override
_PullOutDetailsPageState createState() {
return _PullOutDetailsPageState();
}
}
class _PullOutDetailsPageState extends State<PullOutDetailsPage> {
@override
void dispose() {
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor, backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: DefaultAppBar( appBar: DefaultAppBar(
title: 'Loan Request'.addTranslation, title: 'Pullout Report'.addTranslation,
), ),
body: DefaultTabController( body: DefaultTabController(
length: 2, length: 2,
@ -61,16 +49,15 @@ class _PullOutDetailsPageState extends State<PullOutDetailsPage> {
], ],
), ),
), ),
12.height, 0.height,
TabBarView( TabBarView(
children: [ children: [
Align( Column(
alignment: Alignment.topCenter, children: [
child: InstallationDetailsView( InstallationDetailsView(loanData: loanData!),
loanData: widget.loanData!, ],
),
), ),
const InstallationPullOutFormView(isPullout: true), InstallationPullOutFormView(loanData: loanData!),
], ],
).expanded, ).expanded,
], ],

@ -48,4 +48,16 @@ class LoanProvider extends ChangeNotifier {
} }
return loanData; return loanData;
} }
Future<bool> loanWorkflowAction(Map<String, dynamic> body) async {
try {
Response response = await ApiManager.instance.post(URLs.loanWorkflowAction, body: body, showToast: true);
if (response.statusCode >= 200 && response.statusCode < 300) {
return true;
}
return false;
} catch (error) {
return false;
}
}
} }

Loading…
Cancel
Save