standard / backup loan request creation.

design_3.0_loan_module
Sikander Saleem 1 week ago
parent 05d9224a08
commit 62cc13b1c0

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 0.833008C11.958 0.833008 15.167 4.04196 15.167 8C15.167 11.958 11.958 15.167 8 15.167C4.04196 15.167 0.833008 11.958 0.833008 8C0.833008 4.04196 4.04196 0.833008 8 0.833008ZM8 1.83301C4.59424 1.83301 1.83301 4.59424 1.83301 8C1.83301 11.4058 4.59424 14.167 8 14.167C11.4058 14.167 14.167 11.4058 14.167 8C14.167 4.59424 11.4058 1.83301 8 1.83301ZM8.00098 10.667C8.36897 10.6671 8.66682 10.965 8.66699 11.333C8.66699 11.7011 8.36908 11.9999 8.00098 12H7.99512C7.62693 12 7.32812 11.7012 7.32812 11.333C7.3283 10.965 7.62704 10.667 7.99512 10.667H8.00098ZM8 4.16699C9.01252 4.16699 9.83301 4.98748 9.83301 6C9.83301 6.36418 9.72698 6.70519 9.54297 6.99121C9.42768 7.17037 9.29225 7.34163 9.16797 7.49609C9.14533 7.52423 9.12343 7.55204 9.10156 7.5791C8.99844 7.70673 8.9029 7.82412 8.81543 7.94434C8.59998 8.24054 8.5 8.46358 8.5 8.66699V9C8.5 9.27614 8.27614 9.5 8 9.5C7.72386 9.5 7.5 9.27614 7.5 9V8.66699C7.5 8.13425 7.76118 7.69312 8.00684 7.35547C8.11059 7.21287 8.22473 7.07224 8.32812 6.94434C8.34874 6.91884 8.36904 6.89354 8.38867 6.86914C8.51202 6.71584 8.61726 6.58055 8.70117 6.4502C8.78451 6.32068 8.83301 6.16664 8.83301 6C8.83301 5.53976 8.46024 5.16699 8 5.16699C7.53976 5.16699 7.16699 5.53976 7.16699 6C7.16699 6.27603 6.94298 6.49982 6.66699 6.5C6.39085 6.5 6.16699 6.27614 6.16699 6C6.16699 4.98748 6.98748 4.16699 8 4.16699Z" fill="#3B3D4A"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -4,8 +4,8 @@ class URLs {
static const String appReleaseBuildNumber = "28";
// 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 const host1 = "http://10.201.111.125:9495"; // temporary Server UAT url
// static String _baseUrl = "$_host/mobile";
@ -369,4 +369,10 @@ class URLs {
//survey
static get getQuestionnaire => '$_baseUrl/SurveyQuestionnaire/GetQuestionnaire';
static get submitSurvey => '$_baseUrl/SurveyQuestionnaire/SubmitSurvey';
// load module
static get getLoanPeriod => "$_baseUrl/Lookups/GetLookup?lookupEnum=3051";
static get getMedDepartmentBasedOnSite => "$_baseUrl/TRAFDataSource/GetDepartmentBasedOnSite";
static get getLoanById => '$_baseUrl/Loan/GetLoanById';
static get addLoan => '$_baseUrl/Loan/AddLoan';
}

@ -140,8 +140,7 @@ class AllRequestsProvider extends ChangeNotifier {
return list;
}
if (context.userProvider.isQualityUser) {
list = [10,11];
list = [10, 11];
return list;
}
@ -163,6 +162,7 @@ class AllRequestsProvider extends ChangeNotifier {
if (context.userProvider.isNurse) {
list.add(9); //
}
list.add(12); // loan module
return list;
}

@ -134,7 +134,7 @@ abstract class AppTextStyles {
fontStyle: FontStyle.normal,
decoration: TextDecoration.none,
);
static final TextStyle textFieldLabelStyle= TextStyle(
static final TextStyle textFieldLabelStyle = TextStyle(
fontSize: 11.toScreenWidth,
fontWeight: FontWeight.w500,
color: AppColor.neutral20,
@ -164,14 +164,14 @@ extension CapExtension on String {
String get allInCaps => toUpperCase();
String get cleanupWhitespace => this;//replaceAll(RegExp(r"\s+"), " ");
String get cleanupWhitespace => this; //replaceAll(RegExp(r"\s+"), " ");
String get capitalizeFirstOfEach => this;
//trim().isNotEmpty
// ? trim().toLowerCase().split(" ").map((str) {
// return str.trim()?.inCaps ?? "";
// }).join(" ")
// : "";
//trim().isNotEmpty
// ? trim().toLowerCase().split(" ").map((str) {
// return str.trim()?.inCaps ?? "";
// }).join(" ")
// : "";
}
extension FilesExtension on String {

@ -382,7 +382,7 @@ class MyApp extends StatelessWidget {
CreateSystemInternalAuditForm.id: (_) => const CreateSystemInternalAuditForm(),
UpdateEquipmentInternalAuditPage.id: (_) => UpdateEquipmentInternalAuditPage(),
UpdateSystemInternalAuditPage.id: (_) => UpdateSystemInternalAuditPage(),
CreateLoanRequestView.id: (_) => const CreateLoanRequestView(),
CreateLoanRequestView.id: (_) => CreateLoanRequestView(),
// SwipeSuccessView.routeName: (_) => const SwipeSuccessView(),
// SwipeHistoryView.routeName: (_) => const SwipeHistoryView(),
},

@ -75,7 +75,6 @@ class LoanFormModel {
// "cMWOItemId": null
// }
Map<String, dynamic> toJson() {
return {
"doctorName": docName,
@ -90,12 +89,13 @@ class LoanFormModel {
"vendorRepresentativeName": vendorRepresentativeName,
"vendorNumber": vendorNumber,
"vendorEmail": vendorEmail,
'siteId' : site?.id,
'departmentId' : department?.id,
'siteId': site?.id,
'departmentId': department?.id,
"loanAttachments": loanAttachment != null ? loanAttachment!.map((v) => v.toJson()).toList() : [],
};
}
}
class LoanAttachments {
LoanAttachments({
this.id,

@ -4,12 +4,14 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/device_transfer_provider.dart';
import 'package:test_sa/controllers/validator/validator.dart';
import 'package:test_sa/dashboard_latest/dashboard_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/device/asset.dart';
import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/models/generic_attachment_model.dart';
@ -28,6 +30,7 @@ import 'package:test_sa/modules/loan_module/models/loan_form_model.dart';
import 'package:test_sa/modules/loan_module/models/medical_department_model.dart';
import 'package:test_sa/modules/loan_module/provider/loan_period_provider.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/modules/loan_module/provider/medical_department_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';
@ -47,8 +50,9 @@ import '../../../models/new_models/department.dart';
class CreateLoanRequestView extends StatefulWidget {
static const String id = "/create-loan";
int? workOrderId;
const CreateLoanRequestView({Key? key}) : super(key: key);
CreateLoanRequestView({Key? key, this.workOrderId}) : super(key: key);
@override
_CreateLoanRequestViewState createState() => _CreateLoanRequestViewState();
@ -61,14 +65,16 @@ class _CreateLoanRequestViewState extends State<CreateLoanRequestView> with Tick
Asset? device;
TaskType? selectedType;
final LoanFormModel _loanFormModel = LoanFormModel();
bool isEng = true;
TextEditingController commentController = TextEditingController();
bool get isBackUpRequest => widget.workOrderId != null;
@override
void initState() {
// TODO: implement initState
super.initState();
Provider.of<MedicalDepartmentProvider>(context, listen: false).reset();
Provider.of<LoanPeriodProvider>(context, listen: false).reset();
}
@override
@ -81,33 +87,36 @@ class _CreateLoanRequestViewState extends State<CreateLoanRequestView> with Tick
child: Column(
children: [
SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
// if(isEng)...[
// scanAssetButton(),
if (isBackUpRequest) ...[
scanAssetButton(),
16.height,
],
// ...contactInfoSection(),
// 16.height,
// ],
contactInfoSection(),
...itemDetailsSection(),
16.height,
itemDetailsSection(),
...doctorInfoSection(),
16.height,
...vendorDetailsSection(),
16.height,
vendorDetailsSection(),
23.height,
AttachmentPicker(
label: context.translation.attachments,
attachment: attachments,
buttonColor: AppColor.black10,
onlyImages: false,
buttonIcon: 'image-plus'.toSvgAsset(color: context.isDark ? AppColor.primary10 : AppColor.neutral120),
//verify this if not required delete this ..
onChange: (attachments) {
attachments = attachments;
setState(() {});
},
),
],
).toShadowContainer(context).paddingAll(16),
).toShadowContainer(context, borderRadius: 20),
).expanded,
FooterActionButton.footerContainer(
context: context,
@ -124,10 +133,8 @@ class _CreateLoanRequestViewState extends State<CreateLoanRequestView> with Tick
);
}
Widget contactInfoSection() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
List<Widget> contactInfoSection() {
return [
context.translation.contactInfo.heading6(context).custom(color: AppColor.black10),
8.height,
AppTextFormField(
@ -174,21 +181,82 @@ class _CreateLoanRequestViewState extends State<CreateLoanRequestView> with Tick
},
style: Theme.of(context).textTheme.titleMedium,
),
],
);
];
}
Widget itemDetailsSection() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
'Item Details'.addTranslation.heading6(context).custom(color: AppColor.black10),
List<Widget> doctorInfoSection() {
return [
context.translation.contactInfo.bodyText(context).custom(color: AppColor.black10),
8.height,
AppTextFormField(
initialValue: "",
labelText: "Doctor Name",
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,
onChange: (value) {
_loanFormModel.docName = value;
},
),
8.height,
AppTextFormField(
initialValue: "",
labelText: "Doctor Number",
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.phone,
onChange: (value) {
_loanFormModel.docNumber = value;
},
),
8.height,
AppTextFormField(
initialValue: "",
labelText: "Doctor Email",
validator: (value) {
if ((value ?? "").isEmpty) {
return "Mandatory";
} else {
return Validator.isEmail(value!) ? null : context.translation.emailValidateMessage;
}
},
style: Theme.of(context).textTheme.titleMedium,
backgroundColor: AppColor.fieldBgColor(context),
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
showShadow: false,
textInputType: TextInputType.emailAddress,
onChange: (value) {
_loanFormModel.docEmail = value;
},
),
];
}
List<Widget> itemDetailsSection() {
return [
'Item Details'.addTranslation.bodyText(context).custom(color: AppColor.black10),
8.height,
SingleItemDropDownMenu<Site, SiteProvider>(
context: context,
title: context.translation.site,
initialValue: _loanFormModel.site,
showShadow: false,
validator: (value) {
if (value == null) return "Please select a site";
return null;
},
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
onSelect: (value) {
@ -197,25 +265,14 @@ class _CreateLoanRequestViewState extends State<CreateLoanRequestView> with Tick
},
),
8.height,
//TODO need to check where to get all departments..
// MultipleItemDropDownMenu<TrafDepartment, DepartmentLookupProvider>(
// context: context,
// showAsBottomSheet: true,
// backgroundColor: AppColor.neutral100,
// showShadow: false,
// showCancel: true,
// requestById: context.userProvider.user?.clientId,
// title: "Please specify departments and relations",
// initialValue: departments,
// onSelect: (value) {
// departments = value ?? [];
// trafRequest?.trafDepartments = departments.map((element) => Departments(id: 0, trafId: 0, departmentId: element.id!.toInt())).toList();
// },
// ),
SingleItemDropDownMenu<MedicalDepartmentModel, MedicalDepartmentProvider>(
context: context,
title: context.translation.department,
showShadow: false,
validator: (value) {
if (value == null) return "Please select a department";
return null;
},
showAsBottomSheet: true,
initialValue: _loanFormModel.department,
requestById: context.userProvider.user?.clientId,
@ -228,58 +285,81 @@ class _CreateLoanRequestViewState extends State<CreateLoanRequestView> with Tick
8.height,
AppTextFormField(
labelText: "Item Description",
validator: (value) {
if ((value ?? "").isEmpty) return "Mandatory";
return null;
},
style: Theme.of(context).textTheme.titleMedium,
backgroundColor: AppColor.fieldBgColor(context),
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
hintStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.text,
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
floatingLabelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
showShadow: false,
onSaved: (value) {
textInputType: TextInputType.text,
onChange: (value) {
_loanFormModel.itemDescription = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
Row(
children: [
"help-circle".toSvgAsset(height: 16, width: 16),
8.width,
Text(
"Specify the purpose of the loan (e.g., equipment needed for a scheduled procedure or patient case)",
style: AppTextStyles.tinyFont2.copyWith(fontWeight: FontWeight.w400, color: context.isDark ? Colors.white : const Color(0xff3B3D4A)),
).expanded,
],
),
8.height,
AppTextFormField(
labelText: "Request Description",
validator: (value) {
if ((value ?? "").isEmpty) return "Mandatory";
return null;
},
style: Theme.of(context).textTheme.titleMedium,
backgroundColor: AppColor.fieldBgColor(context),
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
hintStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.text,
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
floatingLabelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
showShadow: false,
onSaved: (value) {
textInputType: TextInputType.text,
onChange: (value) {
_loanFormModel.requestDescription = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: "Model",
validator: (value) {
if ((value ?? "").isEmpty) return "Mandatory";
return null;
},
style: Theme.of(context).textTheme.titleMedium,
backgroundColor: AppColor.fieldBgColor(context),
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
hintStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.text,
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
floatingLabelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
showShadow: false,
onSaved: (value) {
textInputType: TextInputType.text,
onChange: (value) {
_loanFormModel.model = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: "Manufacturer",
validator: (value) {
if ((value ?? "").isEmpty) return "Mandatory";
return null;
},
style: Theme.of(context).textTheme.titleMedium,
backgroundColor: AppColor.fieldBgColor(context),
textAlign: TextAlign.center,
labelStyle: AppTextStyles.textFieldLabelStyle,
hintStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.text,
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
floatingLabelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
showShadow: false,
onSaved: (value) {
textInputType: TextInputType.text,
onChange: (value) {
_loanFormModel.manufacturer = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
SingleItemDropDownMenu<Lookup, LoanPeriodProvider>(
@ -287,6 +367,10 @@ class _CreateLoanRequestViewState extends State<CreateLoanRequestView> with Tick
height: 56.toScreenHeight,
title: 'Loan Period'.addTranslation,
showShadow: false,
validator: (value) {
if (value == null) return "Please select loan period";
return null;
},
backgroundColor: AppColor.fieldBgColor(context),
showAsBottomSheet: true,
initialValue: _loanFormModel.loanProvided,
@ -298,62 +382,84 @@ class _CreateLoanRequestViewState extends State<CreateLoanRequestView> with Tick
},
),
8.height,
],
);
];
}
Widget vendorDetailsSection() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
'Vendor Details'.addTranslation.heading6(context).custom(color: AppColor.black10),
List<Widget> vendorDetailsSection() {
return [
'Vendor Details'.addTranslation.bodyText(context).custom(color: AppColor.black10),
8.height,
AppTextFormField(
labelText: "Name",
initialValue: "",
labelText: "Vendor Name",
validator: (value) {
if ((value ?? "").isEmpty) return "Mandatory";
return null;
},
style: Theme.of(context).textTheme.titleMedium,
backgroundColor: AppColor.fieldBgColor(context),
textAlign: TextAlign.center,
hintText: "Vendor Name",
labelStyle: AppTextStyles.textFieldLabelStyle,
hintStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.text,
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
showShadow: false,
onSaved: (value) {
textInputType: TextInputType.name,
onChange: (value) {
_loanFormModel.vendorName = value;
},
),
8.height,
AppTextFormField(
initialValue: "",
labelText: "Vendor Representative Name",
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.name,
onChange: (value) {
_loanFormModel.vendorRepresentativeName = value;
},
),
8.height,
AppTextFormField(
labelText: "Number",
initialValue: "",
labelText: "Vendor Number",
validator: (value) {
if ((value ?? "").isEmpty) return "Mandatory";
return null;
},
style: Theme.of(context).textTheme.titleMedium,
backgroundColor: AppColor.fieldBgColor(context),
textAlign: TextAlign.center,
hintText: "Vendor Number",
labelStyle: AppTextStyles.textFieldLabelStyle,
hintStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.phone,
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
showShadow: false,
onSaved: (value) {
textInputType: TextInputType.phone,
onChange: (value) {
_loanFormModel.vendorNumber = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
8.height,
AppTextFormField(
labelText: "Email",
initialValue: "",
labelText: "Vendor Email",
validator: (value) {
if ((value ?? "").isEmpty) {
return "Mandatory";
} else {
return Validator.isEmail(value!) ? null : context.translation.emailValidateMessage;
}
},
style: Theme.of(context).textTheme.titleMedium,
backgroundColor: AppColor.fieldBgColor(context),
textAlign: TextAlign.center,
hintText: "Vendor Email",
labelStyle: AppTextStyles.textFieldLabelStyle,
hintStyle: AppTextStyles.textFieldLabelStyle,
textInputType: TextInputType.emailAddress,
labelStyle: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.textColor(context)),
showShadow: false,
onSaved: (value) {
textInputType: TextInputType.emailAddress,
onChange: (value) {
_loanFormModel.vendorEmail = value;
},
style: Theme.of(context).textTheme.titleMedium,
),
],
);
];
}
Widget scanAssetButton() {
@ -369,16 +475,33 @@ class _CreateLoanRequestViewState extends State<CreateLoanRequestView> with Tick
}
Future<void> _submit() async {
if (isBackUpRequest && device == null) {
"Please scan or pick asset".showToast;
return;
}
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
_loanFormModel?.loanAttachment = [];
_loanFormModel.loanAttachment = [];
for (var item in attachments) {
String fileName = ServiceRequestUtils.isLocalUrl(item.name ?? '') ? ("${item.name ?? ''.split("/").last}|${base64Encode(File(item.name ?? '').readAsBytesSync())}") : item.name ?? '';
_loanFormModel?.loanAttachment?.add(LoanAttachments(id: item.id, name: fileName));
_loanFormModel.loanAttachment?.add(LoanAttachments(id: item.id, name: fileName));
}
Utils.showLoading(context);
LoanProvider loanProvider = Provider.of<LoanProvider>(context, listen: false);
// await loanProvider.addLoanRequest(context: context, task: _loanFormModel!);
Map<String, dynamic> body = _loanFormModel.toJson();
body["id"] = 0;
body["requestorUserID"] = context.userProvider.user!.userID;
if (isBackUpRequest) {
body["assetId"] = device!.id;
body["cMWOItemId"] = widget.workOrderId;
}
bool isSuccess = await loanProvider.addLoanRequest(body);
Utils.hideLoading(context);
if (isSuccess) {
Navigator.pop(context);
}
}
}
}

@ -8,7 +8,7 @@ import 'package:test_sa/providers/loading_list_notifier.dart';
class LoanPeriodProvider extends LoadingListNotifier<Lookup> {
@override
Future getData({int?id}) async {
Future getData({int? id}) async {
if (loading == true) return -2;
loading = true;
notifyListeners();

@ -1,8 +1,32 @@
import 'package:flutter/cupertino.dart';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
class LoanProvider extends ChangeNotifier {
Future<bool> addLoanRequest(Map<String, dynamic> body) async {
try {
Response response = await ApiManager.instance.post(URLs.addLoan, body: body);
if (response.statusCode >= 200 && response.statusCode < 300) {
// trafRequestDataModel = TrafRequestDataModel.fromJson(json.decode(response.body)["data"]);
return true;
}
return false;
} catch (error) {
return false;
}
}
Future<bool> getLoanById(int id) async {
try {
Response response = await ApiManager.instance.get(URLs.getLoanById + "?loanId=$id");
if (response.statusCode >= 200 && response.statusCode < 300) {
// trafRequestDataModel = TrafRequestDataModel.fromJson(json.decode(response.body)["data"]);
return true;
}
return false;
} catch (error) {
return false;
}
}
}

@ -213,7 +213,7 @@ class _AppTextFormFieldState extends State<AppTextFormField> {
: !widget.enable
? (widget.enableColor ?? AppColor.neutral40)
: AppColor.background(context)),
errorStyle: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red60),
errorStyle: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red30),
floatingLabelStyle: widget.floatingLabelStyle ?? AppTextStyle.body1.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.white10 : AppColor.neutral20),
hintText: widget.hintText ?? "",
// labelText: (widget.showSpeechToText && _speechToText.isListening) ? "Listening..." : widget.labelText ?? "",

@ -4,6 +4,7 @@ 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/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_text_style.dart';
import 'package:test_sa/new_views/common_widgets/app_loading_manager.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
import 'package:test_sa/views/widgets/bottom_sheets/selection_bottom_sheet.dart';
@ -28,6 +29,8 @@ class SingleItemDropDownMenu<T extends Base, X extends LoadingListNotifier> exte
final Color? backgroundColor; // Now nullable
final bool? loading; // Now nullable
final int? requestById;
final String? Function(T?)? validator;
final AutovalidateMode? autovalidateMode;
/// To use a static data (without calling API)
/// just send [NullableLoadingProvider] as generic data type and fill the [staticData]
@ -48,6 +51,8 @@ class SingleItemDropDownMenu<T extends Base, X extends LoadingListNotifier> exte
this.backgroundColor,
this.loading,
this.requestById,
this.validator,
this.autovalidateMode,
}) : super(key: key);
@override
@ -100,7 +105,15 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
@override
Widget build(BuildContext context) {
final isEmpty = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.isEmpty ?? true;
return AppLoadingManager(
return FormField<T>(
validator: widget.validator,
autovalidateMode: widget.autovalidateMode ?? AutovalidateMode.disabled,
initialValue: widget.initialValue,
builder: (FormFieldState<T> fieldState) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AppLoadingManager(
isLoading: widget.loading ?? ((X == NullableLoadingProvider) ? false : provider?.loading ?? false),
// Provide default value if null
isFailedLoading: (X == NullableLoadingProvider) ? false : provider?.items == null,
@ -157,7 +170,8 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
setState(() {
_selectedItem = isNull ? null : newValue;
});
widget.onSelect!(isNull ? null : newValue); // Non-null assertion after null check
fieldState.didChange(isNull ? null : newValue);
widget.onSelect!(isNull ? null : newValue);
},
items: ((X == NullableLoadingProvider) ? widget.staticData : provider?.items as List<T>)?.map<DropdownMenuItem<T>>((value) {
return DropdownMenuItem<T>(
@ -174,7 +188,7 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
],
).onPress(widget.enabled && widget.showAsFullScreenDialog
? () {
openDialog();
openDialog(fieldState);
}
: widget.enabled
? (widget.showAsBottomSheet
@ -200,6 +214,7 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
setState(() {
_selectedItem = selectedT;
});
fieldState.didChange(selectedT);
widget.onSelect!(selectedT);
},
builderString: (emp) => emp?.name ?? "", // Null-aware operator for emp.name
@ -217,10 +232,21 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
],
),
),
),
if (fieldState.hasError)
Padding(
padding: const EdgeInsets.only(left: 12, top: 4),
child: Text(
fieldState.errorText!,
style: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red30),
),
)
],
);
});
}
void openDialog() async {
void openDialog(FormFieldState<T> fieldState) async {
Widget child = SelectionFullScreenDialog<T>(
// Specify generic type
items: ((X == NullableLoadingProvider) ? widget.staticData : provider?.items as List<T>) ?? [],
@ -233,6 +259,7 @@ class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier
setState(() {
_selectedItem = selectedT;
});
fieldState.didChange(selectedT);
widget.onSelect!(selectedT);
},
builderString: (emp) => emp?.name ?? "", // Null-aware operator for emp.name

@ -67,6 +67,7 @@ class _AllRequestsFilterPageState extends State<AllRequestsFilterPage> {
context.translation.transferAsset: 3,
context.translation.preventiveMaintenance: 4,
context.translation.task: 6,
"Loan Equipment": 12,
};
if (isEngineer) {

@ -44,11 +44,9 @@ class _MyRequestsPageState extends State<MyRequestsPage> {
Request(2, context.translation.gasRefill),
Request(3, context.translation.transferAsset),
Request(4, context.translation.preventiveMaintenance),
];
if (Provider.of<UserProvider>(context, listen: false).user!.type != UsersTypes.normal_user) {
requestsList.add(Request(5, context.translation.recurrentWo));
}
//TODO unCommit this to enable task
requestsList.add(Request(6, context.translation.taskRequest));
@ -68,6 +66,8 @@ class _MyRequestsPageState extends State<MyRequestsPage> {
requestsList.add(Request(11, 'System Internal Audit'));
}
requestsList.add(Request(12, "Loan Equipment"));
if (context.userProvider.isAssessor) {
requestsList = [
Request(null, context.translation.allWorkOrder),

@ -46,7 +46,8 @@ class AssetPicker extends StatelessWidget {
this.showAssetInfo = true,
this.showBorder = false,
this.multiSelection = false,
this.forPPM = false, this.enablePickManually = true,
this.forPPM = false,
this.enablePickManually = true,
this.showLoading = false})
: assert(
multiSelection == false || onMultiAssetPick != null,
@ -66,16 +67,16 @@ class AssetPicker extends StatelessWidget {
decoration: BoxDecoration(
color: buttonColor ?? backgroundColor ?? AppColor.blueStatus(context),
borderRadius: BorderRadius.circular(10),
border: showBorder?Border.all(color: borderColor ?? AppColor.blueStatus(context), width: 2):null,
border: showBorder ? Border.all(color: borderColor ?? AppColor.blueStatus(context), width: 2) : null,
// boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.03), blurRadius: 14)],
),
padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth, vertical: 8.toScreenHeight),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
"scan_asset".toSvgAsset(height: 22, fit: BoxFit.fitHeight, color: context.isDark ? AppColor.neutral20 :iconColor?? Colors.white),
"scan_asset".toSvgAsset(height: 22, fit: BoxFit.fitHeight, color: context.isDark ? AppColor.neutral20 : iconColor ?? Colors.white),
8.width,
' ${label??"Scan or Pick Asset"}'.bodyText(context).custom(color: context.isDark ? AppColor.neutral20 : labelColor?? Colors.white),
' ${label ?? "Scan or Pick Asset"}'.bodyText(context).custom(color: context.isDark ? AppColor.neutral20 : labelColor ?? Colors.white),
],
),
).onPress(() async {
@ -178,7 +179,7 @@ class AssetPicker extends StatelessWidget {
color: Colors.black87,
decoration: TextDecoration.none,
),
).toShimmer(isShow: showLoading,context: context).expanded,
).toShimmer(isShow: showLoading, context: context).expanded,
const Icon(
Icons.info,
color: Color(0xff7D859A),
@ -209,10 +210,10 @@ class AssetPicker extends StatelessWidget {
],
),
8.height,
"${context.translation.assetNo}: ${device.assetNumber}".bodyText2(context).toShimmer(isShow: showLoading,context: context),
"${context.translation.assetNo}: ${device.assetNumber}".bodyText2(context).toShimmer(isShow: showLoading, context: context),
2.height,
// "${context.translation.manufacture}: ${device.modelDefinition?.manufacturerName}".bodyText(context),
"${context.translation.model}: ${device.modelDefinition?.modelName}".bodyText2(context).toShimmer(isShow: showLoading,context: context),
"${context.translation.model}: ${device.modelDefinition?.modelName}".bodyText2(context).toShimmer(isShow: showLoading, context: context),
// "${context.translation.serialNumber}: ${device.assetNumber}".bodyText(context),
// const Divider().defaultStyle(context),
// "${context.translation.department}: ${device.department?.departmentName}".bodyText(context),

Loading…
Cancel
Save