import 'package:get/get.dart'; import 'package:marco/helpers/services/api_service.dart'; import 'package:marco/model/finance/payment_request_list_model.dart'; import 'package:marco/model/finance/payment_request_filter.dart'; import 'package:marco/helpers/services/app_logger.dart'; class PaymentRequestController extends GetxController { // ---------------- Observables ---------------- final RxList paymentRequests = [].obs; final RxBool isLoading = false.obs; final RxString errorMessage = ''.obs; final RxBool isFilterApplied = false.obs; // ---------------- Pagination ---------------- int _pageSize = 20; int _pageNumber = 1; bool _hasMoreData = true; // ---------------- Filters ---------------- RxMap appliedFilter = {}.obs; RxString searchString = ''.obs; // ---------------- Filter Options ---------------- RxList projects = [].obs; RxList payees = [].obs; RxList categories = [].obs; RxList currencies = [].obs; RxList statuses = [].obs; RxList createdBy = [].obs; // ---------------- Fetch Filter Options ---------------- Future fetchPaymentRequestFilterOptions() async { try { final response = await ApiService.getExpensePaymentRequestFilterApi(); if (response != null) { projects.assignAll(response.data.projects); payees.assignAll(response.data.payees); categories.assignAll(response.data.expenseCategory); currencies.assignAll(response.data.currency); statuses.assignAll(response.data.status); createdBy.assignAll(response.data.createdBy); } else { logSafe("Payment request filter API returned null", level: LogLevel.warning); } } catch (e, stack) { logSafe("Exception in fetchPaymentRequestFilterOptions: $e", level: LogLevel.error); logSafe("StackTrace: $stack", level: LogLevel.debug); } } // ---------------- Fetch Payment Requests ---------------- Future fetchPaymentRequests({int pageSize = 20}) async { isLoading.value = true; errorMessage.value = ''; _pageNumber = 1; _pageSize = pageSize; _hasMoreData = true; paymentRequests.clear(); await _fetchPaymentRequestsFromApi(); isLoading.value = false; } // ---------------- Load More ---------------- Future loadMorePaymentRequests() async { if (isLoading.value || !_hasMoreData) return; _pageNumber += 1; isLoading.value = true; await _fetchPaymentRequestsFromApi(); isLoading.value = false; } // ---------------- Internal API Call ---------------- Future _fetchPaymentRequestsFromApi() async { try { final response = await ApiService.getExpensePaymentRequestListApi( pageSize: _pageSize, pageNumber: _pageNumber, filter: appliedFilter, searchString: searchString.value, ); if (response != null && response.data.data.isNotEmpty) { if (_pageNumber == 1) { // First page, replace the list paymentRequests.assignAll(response.data.data); } else { // Append next page items at the end paymentRequests.addAll(response.data.data); } // If returned data is less than page size, no more data if (response.data.data.length < _pageSize) { _hasMoreData = false; } } else { if (_pageNumber == 1) { errorMessage.value = 'No payment requests found.'; } _hasMoreData = false; } } catch (e, stack) { errorMessage.value = 'Failed to fetch payment requests.'; logSafe("Exception in _fetchPaymentRequestsFromApi: $e", level: LogLevel.error); logSafe("StackTrace: $stack", level: LogLevel.debug); _hasMoreData = false; } } // ---------------- Filter Management ---------------- void setFilterApplied(bool applied) { isFilterApplied.value = applied; } void applyFilter(Map filter, {String search = ''}) { appliedFilter.assignAll(filter); searchString.value = search; isFilterApplied.value = filter.isNotEmpty || search.isNotEmpty; fetchPaymentRequests(); } void clearFilter() { appliedFilter.clear(); searchString.value = ''; isFilterApplied.value = false; fetchPaymentRequests(); } }