resolved reabse conflicts
This commit is contained in:
parent
2bda44dd19
commit
b461d5c2a9
@ -8,13 +8,13 @@ import 'package:image_picker/image_picker.dart';
|
||||
import 'package:mime/mime.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import 'package:marco/helpers/services/api_service.dart';
|
||||
import 'package:marco/helpers/services/app_logger.dart';
|
||||
import 'package:marco/helpers/widgets/my_snackbar.dart';
|
||||
import 'package:marco/helpers/widgets/time_stamp_image_helper.dart';
|
||||
import 'package:marco/model/finance/expense_category_model.dart';
|
||||
import 'package:marco/model/finance/currency_list_model.dart';
|
||||
import 'package:marco/model/employees/employee_model.dart';
|
||||
import 'package:on_field_work/helpers/services/api_service.dart';
|
||||
import 'package:on_field_work/helpers/services/app_logger.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_snackbar.dart';
|
||||
import 'package:on_field_work/helpers/widgets/time_stamp_image_helper.dart';
|
||||
import 'package:on_field_work/model/finance/expense_category_model.dart';
|
||||
import 'package:on_field_work/model/finance/currency_list_model.dart';
|
||||
import 'package:on_field_work/model/employees/employee_model.dart';
|
||||
|
||||
class AddPaymentRequestController extends GetxController {
|
||||
// Loading States
|
||||
|
||||
@ -3,20 +3,20 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:marco/controller/task_Planning/daily_task_Planning_controller.dart';
|
||||
import 'package:marco/controller/project_controller.dart';
|
||||
import 'package:marco/controller/tenant/organization_selection_controller.dart';
|
||||
import 'package:marco/controller/tenant/service_controller.dart';
|
||||
import 'package:marco/helpers/widgets/my_spacing.dart';
|
||||
import 'package:marco/helpers/widgets/my_text.dart';
|
||||
import 'package:marco/helpers/widgets/my_snackbar.dart';
|
||||
import 'package:marco/helpers/utils/base_bottom_sheet.dart';
|
||||
import 'package:marco/helpers/widgets/tenant/organization_selector.dart';
|
||||
import 'package:marco/helpers/widgets/tenant/service_selector.dart';
|
||||
import 'package:marco/model/attendance/organization_per_project_list_model.dart';
|
||||
import 'package:marco/model/tenant/tenant_services_model.dart';
|
||||
import 'package:marco/model/employees/employee_model.dart';
|
||||
import 'package:marco/model/employees/multiple_select_role_bottomsheet.dart';
|
||||
import 'package:on_field_work/controller/task_Planning/daily_task_Planning_controller.dart';
|
||||
import 'package:on_field_work/controller/project_controller.dart';
|
||||
import 'package:on_field_work/controller/tenant/organization_selection_controller.dart';
|
||||
import 'package:on_field_work/controller/tenant/service_controller.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_spacing.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_text.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_snackbar.dart';
|
||||
import 'package:on_field_work/helpers/utils/base_bottom_sheet.dart';
|
||||
import 'package:on_field_work/helpers/widgets/tenant/organization_selector.dart';
|
||||
import 'package:on_field_work/helpers/widgets/tenant/service_selector.dart';
|
||||
import 'package:on_field_work/model/attendance/organization_per_project_list_model.dart';
|
||||
import 'package:on_field_work/model/tenant/tenant_services_model.dart';
|
||||
import 'package:on_field_work/model/employees/employee_model.dart';
|
||||
import 'package:on_field_work/model/employees/multiple_select_role_bottomsheet.dart';
|
||||
|
||||
class AssignTaskBottomSheet extends StatefulWidget {
|
||||
final String workLocation;
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:marco/controller/directory/manage_bucket_controller.dart';
|
||||
import 'package:marco/controller/directory/directory_controller.dart';
|
||||
import 'package:marco/helpers/utils/base_bottom_sheet.dart';
|
||||
import 'package:marco/helpers/widgets/my_text.dart';
|
||||
import 'package:marco/helpers/widgets/my_spacing.dart';
|
||||
import 'package:marco/helpers/widgets/my_snackbar.dart';
|
||||
import 'package:marco/model/employees/employee_model.dart';
|
||||
import 'package:marco/model/directory/contact_bucket_list_model.dart';
|
||||
import 'package:marco/model/employees/multiple_select_bottomsheet.dart';
|
||||
import 'package:on_field_work/controller/directory/manage_bucket_controller.dart';
|
||||
import 'package:on_field_work/controller/directory/directory_controller.dart';
|
||||
import 'package:on_field_work/helpers/utils/base_bottom_sheet.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_text.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_spacing.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_snackbar.dart';
|
||||
import 'package:on_field_work/model/employees/employee_model.dart';
|
||||
import 'package:on_field_work/model/directory/contact_bucket_list_model.dart';
|
||||
import 'package:on_field_work/model/employees/multiple_select_bottomsheet.dart';
|
||||
|
||||
class EditBucketBottomSheet {
|
||||
static void show(
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:marco/helpers/utils/base_bottom_sheet.dart';
|
||||
import 'package:marco/helpers/widgets/my_custom_skeleton.dart';
|
||||
import 'package:marco/model/employees/employee_model.dart';
|
||||
import 'package:marco/controller/task_Planning/daily_task_Planning_controller.dart';
|
||||
import 'package:on_field_work/helpers/utils/base_bottom_sheet.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_custom_skeleton.dart';
|
||||
import 'package:on_field_work/model/employees/employee_model.dart';
|
||||
import 'package:on_field_work/controller/task_Planning/daily_task_Planning_controller.dart';
|
||||
|
||||
class MultipleSelectRoleBottomSheet extends StatefulWidget {
|
||||
final String title;
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import 'package:marco/controller/expense/add_expense_controller.dart';
|
||||
import 'package:marco/helpers/utils/mixins/ui_mixin.dart';
|
||||
import 'package:marco/model/expense/expense_type_model.dart';
|
||||
import 'package:marco/model/expense/payment_types_model.dart';
|
||||
// import 'package:marco/model/expense/employee_selector_bottom_sheet.dart';
|
||||
import 'package:marco/helpers/utils/base_bottom_sheet.dart';
|
||||
import 'package:marco/helpers/utils/validators.dart';
|
||||
import 'package:marco/helpers/widgets/my_spacing.dart';
|
||||
import 'package:marco/helpers/widgets/my_snackbar.dart';
|
||||
import 'package:marco/helpers/widgets/my_confirmation_dialog.dart';
|
||||
import 'package:marco/helpers/widgets/expense/expense_form_widgets.dart';
|
||||
import 'package:marco/model/employees/employee_model.dart';
|
||||
import 'package:marco/model/employees/multiple_select_bottomsheet.dart';
|
||||
import 'package:on_field_work/controller/expense/add_expense_controller.dart';
|
||||
import 'package:on_field_work/helpers/utils/mixins/ui_mixin.dart';
|
||||
import 'package:on_field_work/model/expense/expense_type_model.dart';
|
||||
import 'package:on_field_work/model/expense/payment_types_model.dart';
|
||||
// import 'package:on_field_work/model/expense/employee_selector_bottom_sheet.dart';
|
||||
import 'package:on_field_work/helpers/utils/base_bottom_sheet.dart';
|
||||
import 'package:on_field_work/helpers/utils/validators.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_spacing.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_snackbar.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_confirmation_dialog.dart';
|
||||
import 'package:on_field_work/helpers/widgets/expense/expense_form_widgets.dart';
|
||||
import 'package:on_field_work/model/employees/employee_model.dart';
|
||||
import 'package:on_field_work/model/employees/multiple_select_bottomsheet.dart';
|
||||
|
||||
/// Show bottom sheet wrapper
|
||||
Future<T?> showAddExpenseBottomSheet<T>({
|
||||
|
||||
@ -1,18 +1,16 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:marco/controller/finance/add_payment_request_controller.dart';
|
||||
import 'package:marco/helpers/utils/mixins/ui_mixin.dart';
|
||||
import 'package:marco/helpers/utils/base_bottom_sheet.dart';
|
||||
import 'package:marco/helpers/utils/validators.dart';
|
||||
import 'package:marco/helpers/widgets/my_spacing.dart';
|
||||
import 'package:marco/helpers/widgets/my_snackbar.dart';
|
||||
import 'package:marco/helpers/widgets/expense/expense_form_widgets.dart';
|
||||
import 'package:marco/helpers/widgets/my_confirmation_dialog.dart';
|
||||
import 'package:marco/model/employees/multiple_select_bottomsheet.dart';
|
||||
import 'package:marco/model/employees/employee_model.dart';
|
||||
import 'package:marco/model/employees/multiple_select_bottomsheet.dart';
|
||||
import 'package:marco/model/employees/employee_model.dart';
|
||||
import 'package:on_field_work/controller/finance/add_payment_request_controller.dart';
|
||||
import 'package:on_field_work/helpers/utils/mixins/ui_mixin.dart';
|
||||
import 'package:on_field_work/helpers/utils/base_bottom_sheet.dart';
|
||||
import 'package:on_field_work/helpers/utils/validators.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_spacing.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_snackbar.dart';
|
||||
import 'package:on_field_work/helpers/widgets/expense/expense_form_widgets.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_confirmation_dialog.dart';
|
||||
import 'package:on_field_work/model/employees/multiple_select_bottomsheet.dart';
|
||||
import 'package:on_field_work/model/employees/employee_model.dart';
|
||||
|
||||
Future<T?> showPaymentRequestBottomSheet<T>({
|
||||
bool isEdit = false,
|
||||
@ -80,10 +78,10 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
'name': data["projectName"],
|
||||
};
|
||||
|
||||
|
||||
controller.selectedPayee.value = data["payee"] ?? "";
|
||||
controller.isAdvancePayment.value = data["isAdvancePayment"] ?? false;
|
||||
|
||||
// When categories and currencies load, set selected ones
|
||||
everAll([controller.categories, controller.currencies], (_) {
|
||||
controller.selectedCategory.value = controller.categories
|
||||
.firstWhereOrNull((c) => c.id == data["expenseCategoryId"]);
|
||||
@ -117,52 +115,21 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Obx(() => SafeArea(
|
||||
return Obx(
|
||||
() => SafeArea(
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: BaseBottomSheet(
|
||||
title: widget.isEdit
|
||||
? "Edit Payment Request"
|
||||
: "Create Payment Request",
|
||||
title: widget.isEdit ? "Edit Payment Request" : "Create Payment Request",
|
||||
isSubmitting: controller.isSubmitting.value,
|
||||
onCancel: Get.back,
|
||||
submitText: "Save as Draft",
|
||||
onSubmit: () async {
|
||||
if (_formKey.currentState!.validate() &&
|
||||
_validateSelections()) {
|
||||
if (_formKey.currentState!.validate() && _validateSelections()) {
|
||||
bool success = false;
|
||||
|
||||
if (widget.isEdit && widget.existingData != null) {
|
||||
final requestId =
|
||||
widget.existingData!['id']?.toString() ?? '';
|
||||
if (requestId.isNotEmpty) {
|
||||
success = await controller.submitEditedPaymentRequest(
|
||||
requestId: requestId);
|
||||
} else {
|
||||
_showError("Invalid Payment Request ID");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
success = await controller.submitPaymentRequest();
|
||||
}
|
||||
return Obx(() => SafeArea(
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: BaseBottomSheet(
|
||||
title: widget.isEdit
|
||||
? "Edit Payment Request"
|
||||
: "Create Payment Request",
|
||||
isSubmitting: controller.isSubmitting.value,
|
||||
onCancel: Get.back,
|
||||
submitText: "Save as Draft",
|
||||
onSubmit: () async {
|
||||
if (_formKey.currentState!.validate() &&
|
||||
_validateSelections()) {
|
||||
bool success = false;
|
||||
|
||||
if (widget.isEdit && widget.existingData != null) {
|
||||
final requestId =
|
||||
widget.existingData!['id']?.toString() ?? '';
|
||||
final requestId = widget.existingData!['id']?.toString() ?? '';
|
||||
if (requestId.isNotEmpty) {
|
||||
success = await controller.submitEditedPaymentRequest(
|
||||
requestId: requestId);
|
||||
@ -174,9 +141,6 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
success = await controller.submitPaymentRequest();
|
||||
}
|
||||
|
||||
if (success) {
|
||||
Get.back();
|
||||
widget.onUpdated?.call();
|
||||
if (success) {
|
||||
Get.back();
|
||||
widget.onUpdated?.call();
|
||||
@ -191,23 +155,6 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
}
|
||||
}
|
||||
},
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.only(bottom: 20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_buildDropdown(
|
||||
showAppSnackbar(
|
||||
title: "Success",
|
||||
message: widget.isEdit
|
||||
? "Payment request updated successfully!"
|
||||
: "Payment request created successfully!",
|
||||
type: SnackbarType.success,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.only(bottom: 20),
|
||||
child: Column(
|
||||
@ -217,23 +164,17 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
_buildDropdown(
|
||||
"Select Project",
|
||||
Icons.work_outline,
|
||||
controller.selectedProject.value?['name'] ??
|
||||
"Select Project",
|
||||
controller.selectedProject.value?['name'] ?? "Select Project",
|
||||
controller.globalProjects,
|
||||
(p) => p['name'],
|
||||
controller.selectProject,
|
||||
key: _projectDropdownKey,
|
||||
),
|
||||
_gap(),
|
||||
_buildDropdown(
|
||||
key: _projectDropdownKey,
|
||||
),
|
||||
_gap(),
|
||||
_buildDropdown(
|
||||
"Expense Category",
|
||||
Icons.category_outlined,
|
||||
controller.selectedCategory.value?.name ??
|
||||
"Select Category",
|
||||
controller.selectedCategory.value?.name ?? "Select Category",
|
||||
controller.categories,
|
||||
(c) => c.name,
|
||||
controller.selectCategory,
|
||||
@ -242,43 +183,10 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
_gap(),
|
||||
_buildTextField("Title", Icons.title_outlined,
|
||||
controller.titleController,
|
||||
hint: "Enter title",
|
||||
validator: Validators.requiredField),
|
||||
hint: "Enter title", validator: Validators.requiredField),
|
||||
_gap(),
|
||||
_buildRadio(
|
||||
"Is Advance Payment",
|
||||
Icons.attach_money_outlined,
|
||||
controller.isAdvancePayment,
|
||||
["Yes", "No"]),
|
||||
_gap(),
|
||||
_buildDueDateField(),
|
||||
_gap(),
|
||||
_buildTextField("Amount", Icons.currency_rupee,
|
||||
controller.amountController,
|
||||
hint: "Enter Amount",
|
||||
keyboardType: TextInputType.number,
|
||||
validator: (v) => (v != null &&
|
||||
v.isNotEmpty &&
|
||||
double.tryParse(v) != null)
|
||||
? null
|
||||
: "Enter valid amount"),
|
||||
_gap(),
|
||||
_buildPayeeField(),
|
||||
_gap(),
|
||||
_buildDropdown(
|
||||
key: _categoryDropdownKey,
|
||||
),
|
||||
_gap(),
|
||||
_buildTextField("Title", Icons.title_outlined,
|
||||
controller.titleController,
|
||||
hint: "Enter title",
|
||||
validator: Validators.requiredField),
|
||||
_gap(),
|
||||
_buildRadio(
|
||||
"Is Advance Payment",
|
||||
Icons.attach_money_outlined,
|
||||
controller.isAdvancePayment,
|
||||
["Yes", "No"]),
|
||||
_buildRadio("Is Advance Payment", Icons.attach_money_outlined,
|
||||
controller.isAdvancePayment, ["Yes", "No"]),
|
||||
_gap(),
|
||||
_buildDueDateField(),
|
||||
_gap(),
|
||||
@ -297,8 +205,7 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
_buildDropdown(
|
||||
"Currency",
|
||||
Icons.monetization_on_outlined,
|
||||
controller.selectedCurrency.value?.currencyName ??
|
||||
"Select Currency",
|
||||
controller.selectedCurrency.value?.currencyName ?? "Select Currency",
|
||||
controller.currencies,
|
||||
(c) => c.currencyName,
|
||||
controller.selectCurrency,
|
||||
@ -315,23 +222,11 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
MySpacing.height(30),
|
||||
],
|
||||
),
|
||||
key: _currencyDropdownKey,
|
||||
),
|
||||
_gap(),
|
||||
_buildTextField("Description", Icons.description_outlined,
|
||||
controller.descriptionController,
|
||||
hint: "Enter description",
|
||||
maxLines: 3,
|
||||
validator: Validators.requiredField),
|
||||
_gap(),
|
||||
_buildAttachmentsSection(),
|
||||
MySpacing.height(30),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDropdown<T>(String title, IconData icon, String value,
|
||||
@ -345,7 +240,8 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
DropdownTile(
|
||||
key: key,
|
||||
title: value,
|
||||
onTap: () => _showOptionList(options, getLabel, onSelected, key)),
|
||||
onTap: () => _showOptionList(options, getLabel, onSelected, key),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@ -374,7 +270,7 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
}
|
||||
|
||||
Widget _buildRadio(
|
||||
String title, IconData icon, RxBool controller, List<String> labels) {
|
||||
String title, IconData icon, RxBool controllerBool, List<String> labels) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@ -394,16 +290,15 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
final label = entry.value;
|
||||
final value = i == 0;
|
||||
|
||||
|
||||
return Expanded(
|
||||
child: RadioListTile<bool>(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text(label),
|
||||
value: value,
|
||||
groupValue: controller.value,
|
||||
groupValue: controllerBool.value,
|
||||
activeColor: contentTheme.primary,
|
||||
onChanged: (val) =>
|
||||
val != null ? controller.value = val : null,
|
||||
val != null ? controllerBool.value = val : null,
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
@ -417,9 +312,7 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SectionTitle(
|
||||
icon: Icons.calendar_today,
|
||||
title: "Due To Date",
|
||||
requiredField: true),
|
||||
icon: Icons.calendar_today, title: "Due To Date", requiredField: true),
|
||||
MySpacing.height(6),
|
||||
GestureDetector(
|
||||
onTap: () => controller.pickDueDate(context),
|
||||
@ -447,7 +340,6 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPayeeField() {
|
||||
Widget _buildPayeeField() {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@ -458,27 +350,6 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
requiredField: true,
|
||||
),
|
||||
MySpacing.height(6),
|
||||
GestureDetector(
|
||||
onTap: _showPayeeSelector,
|
||||
child: TileContainer(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Obx(() => Text(
|
||||
controller.selectedPayee.value?.name ?? "Select Payee",
|
||||
style: const TextStyle(fontSize: 15),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
)),
|
||||
),
|
||||
const Icon(Icons.arrow_drop_down, size: 22),
|
||||
],
|
||||
const SectionTitle(
|
||||
icon: Icons.person_outline,
|
||||
title: "Payee",
|
||||
requiredField: true,
|
||||
),
|
||||
MySpacing.height(6),
|
||||
GestureDetector(
|
||||
onTap: _showPayeeSelector,
|
||||
child: TileContainer(
|
||||
@ -498,7 +369,6 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
const SizedBox(height: 6),
|
||||
],
|
||||
);
|
||||
}
|
||||
@ -586,8 +456,7 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
return;
|
||||
}
|
||||
|
||||
final RenderBox button =
|
||||
key.currentContext!.findRenderObject() as RenderBox;
|
||||
final RenderBox button = key.currentContext!.findRenderObject() as RenderBox;
|
||||
final RenderBox overlay =
|
||||
Overlay.of(context).context.findRenderObject() as RenderBox;
|
||||
final position = button.localToGlobal(Offset.zero, ancestor: overlay);
|
||||
@ -601,8 +470,7 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
0),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
items: options
|
||||
.map(
|
||||
(opt) => PopupMenuItem<T>(value: opt, child: Text(getLabel(opt))))
|
||||
.map((opt) => PopupMenuItem<T>(value: opt, child: Text(getLabel(opt))))
|
||||
.toList(),
|
||||
);
|
||||
|
||||
@ -617,7 +485,6 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
if (controller.selectedCategory.value == null) {
|
||||
return _showError("Please select a category");
|
||||
}
|
||||
if (controller.selectedPayee.value == null) {
|
||||
if (controller.selectedPayee.value == null) {
|
||||
return _showError("Please select a payee");
|
||||
}
|
||||
@ -646,25 +513,6 @@ class _PaymentRequestBottomSheetState extends State<_PaymentRequestBottomSheet>
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _showPayeeSelector() async {
|
||||
final result = await showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (_) => EmployeeSelectionBottomSheet(
|
||||
title: "Select Payee",
|
||||
multipleSelection: false,
|
||||
initiallySelected: controller.selectedPayee.value != null
|
||||
? [controller.selectedPayee.value!]
|
||||
: [],
|
||||
),
|
||||
);
|
||||
|
||||
if (result is EmployeeModel) {
|
||||
controller.selectedPayee.value = result;
|
||||
}
|
||||
}
|
||||
|
||||
bool _showError(String msg) {
|
||||
showAppSnackbar(title: "Error", message: msg, type: SnackbarType.error);
|
||||
return false;
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:marco/controller/finance/payment_request_controller.dart';
|
||||
import 'package:marco/helpers/utils/base_bottom_sheet.dart';
|
||||
import 'package:marco/helpers/widgets/my_spacing.dart';
|
||||
import 'package:marco/helpers/widgets/my_text.dart';
|
||||
import 'package:marco/helpers/widgets/my_text_style.dart';
|
||||
import 'package:marco/helpers/utils/mixins/ui_mixin.dart';
|
||||
import 'package:marco/helpers/widgets/date_range_picker.dart';
|
||||
import 'package:marco/model/employees/employee_model.dart';
|
||||
import 'package:marco/model/employees/multiple_select_bottomsheet.dart';
|
||||
import 'package:on_field_work/controller/finance/payment_request_controller.dart';
|
||||
import 'package:on_field_work/helpers/utils/base_bottom_sheet.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_spacing.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_text.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_text_style.dart';
|
||||
import 'package:on_field_work/helpers/utils/mixins/ui_mixin.dart';
|
||||
import 'package:on_field_work/helpers/widgets/date_range_picker.dart';
|
||||
import 'package:on_field_work/model/employees/employee_model.dart';
|
||||
import 'package:on_field_work/model/employees/multiple_select_bottomsheet.dart';
|
||||
|
||||
class PaymentRequestFilterBottomSheet extends StatefulWidget {
|
||||
final PaymentRequestController controller;
|
||||
|
||||
@ -2,15 +2,15 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:marco/controller/expense/expense_screen_controller.dart';
|
||||
import 'package:marco/helpers/utils/base_bottom_sheet.dart';
|
||||
import 'package:marco/helpers/widgets/my_spacing.dart';
|
||||
import 'package:marco/helpers/widgets/my_text.dart';
|
||||
import 'package:marco/helpers/widgets/my_text_style.dart';
|
||||
import 'package:marco/model/employees/employee_model.dart';
|
||||
import 'package:marco/helpers/utils/mixins/ui_mixin.dart';
|
||||
import 'package:marco/helpers/widgets/date_range_picker.dart';
|
||||
import 'package:marco/model/employees/multiple_select_bottomsheet.dart';
|
||||
import 'package:on_field_work/controller/expense/expense_screen_controller.dart';
|
||||
import 'package:on_field_work/helpers/utils/base_bottom_sheet.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_spacing.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_text.dart';
|
||||
import 'package:on_field_work/helpers/widgets/my_text_style.dart';
|
||||
import 'package:on_field_work/model/employees/employee_model.dart';
|
||||
import 'package:on_field_work/helpers/utils/mixins/ui_mixin.dart';
|
||||
import 'package:on_field_work/helpers/widgets/date_range_picker.dart';
|
||||
import 'package:on_field_work/model/employees/multiple_select_bottomsheet.dart';
|
||||
|
||||
|
||||
class ExpenseFilterBottomSheet extends StatefulWidget {
|
||||
|
||||
@ -35,8 +35,6 @@ class _AdvancePaymentScreenState extends State<AdvancePaymentScreen>
|
||||
}
|
||||
});
|
||||
|
||||
_searchCtrl.addListener(() {
|
||||
controller.searchQuery.value = _searchCtrl.text.trim();
|
||||
_searchCtrl.addListener(() {
|
||||
controller.searchQuery.value = _searchCtrl.text.trim();
|
||||
});
|
||||
@ -52,7 +50,6 @@ class _AdvancePaymentScreenState extends State<AdvancePaymentScreen>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: const Color(0xFFF5F5F5),
|
||||
backgroundColor: const Color(0xFFF5F5F5),
|
||||
appBar: _buildAppBar(),
|
||||
body: SafeArea(
|
||||
@ -75,65 +72,18 @@ class _AdvancePaymentScreenState extends State<AdvancePaymentScreen>
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: () {
|
||||
FocusScopeNode currentFocus = FocusScope.of(context);
|
||||
if (!currentFocus.hasPrimaryFocus) {
|
||||
currentFocus.unfocus();
|
||||
}
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
final emp = controller.selectedEmployee.value;
|
||||
if (emp != null) {
|
||||
await controller.fetchAdvancePayments(emp.id.toString());
|
||||
}
|
||||
},
|
||||
color: Colors.white,
|
||||
backgroundColor: contentTheme.primary,
|
||||
strokeWidth: 2.5,
|
||||
displacement: 60,
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: () {
|
||||
FocusScopeNode currentFocus = FocusScope.of(context);
|
||||
if (!currentFocus.hasPrimaryFocus) {
|
||||
currentFocus.unfocus();
|
||||
}
|
||||
},
|
||||
|
||||
// ---------------- PORTRAIT (UNCHANGED) ----------------
|
||||
child: !isLandscape
|
||||
? SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
child: Container(
|
||||
color: const Color(0xFFF5F5F5),
|
||||
child: Column(
|
||||
children: [
|
||||
_buildSearchBar(),
|
||||
_buildEmployeeDropdown(context),
|
||||
_buildTopBalance(),
|
||||
_buildPaymentList(),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// ---------------- LANDSCAPE (FIXED) ----------------
|
||||
: SingleChildScrollView(
|
||||
child: SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
color: const Color(0xFFF5F5F5),
|
||||
|
||||
// ❗ Removed IntrinsicHeight
|
||||
// ❗ Removed ConstrainedBox
|
||||
// Dropdown can now open freely
|
||||
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
_buildSearchBar(),
|
||||
_buildEmployeeDropdown(
|
||||
context), // now overlay works
|
||||
_buildEmployeeDropdown(context),
|
||||
_buildTopBalance(),
|
||||
_buildPaymentList(),
|
||||
],
|
||||
@ -223,20 +173,6 @@ class _AdvancePaymentScreenState extends State<AdvancePaymentScreen>
|
||||
child: TextField(
|
||||
controller: _searchCtrl,
|
||||
focusNode: _searchFocus,
|
||||
onTap: () {
|
||||
Future.delayed(const Duration(milliseconds: 50), () {
|
||||
if (mounted) {
|
||||
FocusScope.of(context).requestFocus(_searchFocus);
|
||||
}
|
||||
});
|
||||
},
|
||||
onTap: () {
|
||||
Future.delayed(const Duration(milliseconds: 50), () {
|
||||
if (mounted) {
|
||||
FocusScope.of(context).requestFocus(_searchFocus);
|
||||
}
|
||||
});
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 12, vertical: 0),
|
||||
@ -310,17 +246,10 @@ class _AdvancePaymentScreenState extends State<AdvancePaymentScreen>
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
controller.selectEmployee(e);
|
||||
_searchCtrl
|
||||
..text = e.name
|
||||
..selection = TextSelection.fromPosition(
|
||||
TextPosition(offset: e.name.length),
|
||||
);
|
||||
|
||||
_searchCtrl
|
||||
..text = e.name
|
||||
..selection = TextSelection.fromPosition(
|
||||
TextPosition(offset: e.name.length),
|
||||
);
|
||||
_searchCtrl.text = e.name;
|
||||
_searchCtrl.selection =
|
||||
TextSelection.fromPosition(TextPosition(offset: e.name.length));
|
||||
|
||||
FocusScope.of(context).unfocus();
|
||||
SystemChannels.textInput.invokeMethod('TextInput.hide');
|
||||
@ -406,7 +335,6 @@ class _AdvancePaymentScreenState extends State<AdvancePaymentScreen>
|
||||
);
|
||||
}
|
||||
|
||||
// ✅ No employee selected yet
|
||||
if (controller.selectedEmployee.value == null) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.only(top: 100),
|
||||
@ -414,7 +342,6 @@ class _AdvancePaymentScreenState extends State<AdvancePaymentScreen>
|
||||
);
|
||||
}
|
||||
|
||||
// ✅ Employee selected but no payments found
|
||||
if (controller.payments.isEmpty) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.only(top: 100),
|
||||
@ -424,7 +351,6 @@ class _AdvancePaymentScreenState extends State<AdvancePaymentScreen>
|
||||
);
|
||||
}
|
||||
|
||||
// ✅ Payments available
|
||||
return ListView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
@ -439,28 +365,27 @@ class _AdvancePaymentScreenState extends State<AdvancePaymentScreen>
|
||||
// ---------------- Payment Item ----------------
|
||||
Widget _buildPaymentItem(dynamic item) {
|
||||
final dateStr = (item.date ?? '').toString();
|
||||
DateTime? parsedDate;
|
||||
DateTime? parsed;
|
||||
|
||||
try {
|
||||
parsedDate = DateTime.parse(dateStr);
|
||||
parsed = DateTime.parse(dateStr);
|
||||
} catch (_) {}
|
||||
|
||||
final formattedDate = parsedDate != null
|
||||
? DateFormat('dd MMM yyyy').format(parsedDate)
|
||||
final formattedDate = parsed != null
|
||||
? DateFormat('dd MMM yyyy').format(parsed)
|
||||
: (dateStr.isNotEmpty ? dateStr : '—');
|
||||
|
||||
|
||||
|
||||
final project = item.name ?? '';
|
||||
final desc = item.title ?? '';
|
||||
final amount = (item.amount ?? 0).toDouble();
|
||||
final isCredit = amount >= 0;
|
||||
final accentColor = isCredit ? Colors.green.shade700 : Colors.red.shade700;
|
||||
final accent = isCredit ? Colors.green.shade700 : Colors.red.shade700;
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[100],
|
||||
border: Border(
|
||||
border: const Border(
|
||||
bottom: BorderSide(color: Color(0xFFE0E0E0), width: 0.9),
|
||||
),
|
||||
),
|
||||
@ -472,17 +397,9 @@ class _AdvancePaymentScreenState extends State<AdvancePaymentScreen>
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
formattedDate,
|
||||
Text(formattedDate,
|
||||
style:
|
||||
TextStyle(fontSize: 12, color: Colors.grey.shade600),
|
||||
),
|
||||
|
||||
|
||||
],
|
||||
),
|
||||
TextStyle(fontSize: 12, color: Colors.grey.shade600)),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
project.isNotEmpty ? project : 'No Project',
|
||||
@ -497,10 +414,7 @@ class _AdvancePaymentScreenState extends State<AdvancePaymentScreen>
|
||||
desc.isNotEmpty ? desc : 'No Details',
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.grey.shade700,
|
||||
),
|
||||
style: TextStyle(fontSize: 13, color: Colors.grey.shade700),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -511,7 +425,7 @@ class _AdvancePaymentScreenState extends State<AdvancePaymentScreen>
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: accentColor,
|
||||
color: accent,
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -520,16 +434,16 @@ class _AdvancePaymentScreenState extends State<AdvancePaymentScreen>
|
||||
}
|
||||
|
||||
// ---------------- Utilities ----------------
|
||||
String _initials(String? firstName, [String? lastName]) {
|
||||
if ((firstName?.isEmpty ?? true) && (lastName?.isEmpty ?? true)) return '?';
|
||||
return ((firstName?.isNotEmpty == true ? firstName![0] : '') +
|
||||
(lastName?.isNotEmpty == true ? lastName![0] : ''))
|
||||
String _initials(String? first, [String? last]) {
|
||||
if ((first?.isEmpty ?? true) && (last?.isEmpty ?? true)) return '?';
|
||||
return ((first?.isNotEmpty == true ? first![0] : '') +
|
||||
(last?.isNotEmpty == true ? last![0] : ''))
|
||||
.toUpperCase();
|
||||
}
|
||||
|
||||
String _formatAmount(num amount) {
|
||||
final format = NumberFormat('#,##,###.##', 'en_IN');
|
||||
return format.format(amount);
|
||||
final f = NumberFormat('#,##,###.##', 'en_IN');
|
||||
return f.format(amount);
|
||||
}
|
||||
|
||||
static Color _avatarColorFor(String name) {
|
||||
@ -542,7 +456,7 @@ class _AdvancePaymentScreenState extends State<AdvancePaymentScreen>
|
||||
Colors.teal,
|
||||
Colors.amber,
|
||||
];
|
||||
final hash = name.codeUnits.fold(0, (p, e) => p + e);
|
||||
final hash = name.codeUnits.fold(0, (p, c) => p + c);
|
||||
return colors[hash % colors.length];
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user