182 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			182 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'package:flutter/material.dart';
 | |
| import 'package:get/get.dart';
 | |
| import 'package:marco/helpers/services/api_service.dart';
 | |
| import 'package:marco/model/document/document_filter_model.dart';
 | |
| import 'package:marco/model/document/documents_list_model.dart';
 | |
| 
 | |
| class DocumentController extends GetxController {
 | |
|   // ------------------ Observables ---------------------
 | |
|   var isLoading = false.obs;
 | |
|   var documents = <DocumentItem>[].obs;
 | |
|   var filters = Rxn<DocumentFiltersData>();
 | |
| 
 | |
|   // ✅ Selected filters (multi-select support)
 | |
|   var selectedUploadedBy = <String>[].obs;
 | |
|   var selectedCategory = <String>[].obs;
 | |
|   var selectedType = <String>[].obs;
 | |
|   var selectedTag = <String>[].obs;
 | |
| 
 | |
|   // Pagination state
 | |
|   var pageNumber = 1.obs;
 | |
|   final int pageSize = 20;
 | |
|   var hasMore = true.obs;
 | |
| 
 | |
|   // Error message
 | |
|   var errorMessage = "".obs;
 | |
| 
 | |
|   // NEW: show inactive toggle
 | |
|   var showInactive = false.obs;
 | |
| 
 | |
|   // NEW: search
 | |
|   var searchQuery = ''.obs;
 | |
|   var searchController = TextEditingController();
 | |
| // New filter fields
 | |
|   var isUploadedAt = true.obs;
 | |
|   var isVerified = RxnBool();
 | |
|   var startDate = Rxn<String>();
 | |
|   var endDate = Rxn<String>();
 | |
| 
 | |
|   // ------------------ API Calls -----------------------
 | |
| 
 | |
|   /// Fetch Document Filters for an Entity
 | |
|   Future<void> fetchFilters(String entityTypeId) async {
 | |
|     try {
 | |
|       isLoading.value = true;
 | |
|       final response = await ApiService.getDocumentFilters(entityTypeId);
 | |
| 
 | |
|       if (response != null && response.success) {
 | |
|         filters.value = response.data;
 | |
|       } else {
 | |
|         errorMessage.value = response?.message ?? "Failed to fetch filters";
 | |
|       }
 | |
|     } catch (e) {
 | |
|       errorMessage.value = "Error fetching filters: $e";
 | |
|     } finally {
 | |
|       isLoading.value = false;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /// Toggle document active/inactive state
 | |
|   Future<bool> toggleDocumentActive(
 | |
|     String id, {
 | |
|     required bool isActive,
 | |
|     required String entityTypeId,
 | |
|     required String entityId,
 | |
|   }) async {
 | |
|     try {
 | |
|       isLoading.value = true;
 | |
|       final success =
 | |
|           await ApiService.deleteDocumentApi(id: id, isActive: isActive);
 | |
| 
 | |
|       if (success) {
 | |
|         // 🔥 Always fetch fresh list after toggle
 | |
|         await fetchDocuments(
 | |
|           entityTypeId: entityTypeId,
 | |
|           entityId: entityId,
 | |
|           reset: true,
 | |
|         );
 | |
|         return true;
 | |
|       } else {
 | |
|         errorMessage.value = "Failed to update document state";
 | |
|         return false;
 | |
|       }
 | |
|     } catch (e) {
 | |
|       errorMessage.value = "Error updating document: $e";
 | |
|       return false;
 | |
|     } finally {
 | |
|       isLoading.value = false;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /// Permanently delete a document (or deactivate depending on API)
 | |
|   Future<bool> deleteDocument(String id, {bool isActive = false}) async {
 | |
|     try {
 | |
|       isLoading.value = true;
 | |
|       final success =
 | |
|           await ApiService.deleteDocumentApi(id: id, isActive: isActive);
 | |
| 
 | |
|       if (success) {
 | |
|         // remove from local list immediately for better UX
 | |
|         documents.removeWhere((doc) => doc.id == id);
 | |
|         return true;
 | |
|       } else {
 | |
|         errorMessage.value = "Failed to delete document";
 | |
|         return false;
 | |
|       }
 | |
|     } catch (e) {
 | |
|       errorMessage.value = "Error deleting document: $e";
 | |
|       return false;
 | |
|     } finally {
 | |
|       isLoading.value = false;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /// Fetch Documents for an entity
 | |
|   Future<void> fetchDocuments({
 | |
|     required String entityTypeId,
 | |
|     required String entityId,
 | |
|     String? filter,
 | |
|     String? searchString,
 | |
|     bool reset = false,
 | |
|   }) async {
 | |
|     try {
 | |
|       if (reset) {
 | |
|         pageNumber.value = 1;
 | |
|         documents.clear();
 | |
|         hasMore.value = true;
 | |
|       }
 | |
| 
 | |
|       if (!hasMore.value) return;
 | |
| 
 | |
|       isLoading.value = true;
 | |
| 
 | |
|       final response = await ApiService.getDocumentListApi(
 | |
|         entityTypeId: entityTypeId,
 | |
|         entityId: entityId,
 | |
|         filter: filter ?? "",
 | |
|         searchString: searchString ?? searchQuery.value,
 | |
|         pageNumber: pageNumber.value,
 | |
|         pageSize: pageSize,
 | |
|         isActive: !showInactive.value,
 | |
|       );
 | |
| 
 | |
|       if (response != null && response.success) {
 | |
|         if (response.data.data.isNotEmpty) {
 | |
|           documents.addAll(response.data.data);
 | |
|           pageNumber.value++;
 | |
|         } else {
 | |
|           hasMore.value = false;
 | |
|         }
 | |
|       } else {
 | |
|         errorMessage.value = response?.message ?? "Failed to fetch documents";
 | |
|       }
 | |
|     } catch (e) {
 | |
|       errorMessage.value = "Error fetching documents: $e";
 | |
|     } finally {
 | |
|       isLoading.value = false;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // ------------------ Helpers -----------------------
 | |
| 
 | |
|   /// Clear selected filters
 | |
|   void clearFilters() {
 | |
|     selectedUploadedBy.clear();
 | |
|     selectedCategory.clear();
 | |
|     selectedType.clear();
 | |
|     selectedTag.clear();
 | |
|     isUploadedAt.value = true;
 | |
|     isVerified.value = null;
 | |
|     startDate.value = null;
 | |
|     endDate.value = null;
 | |
|   }
 | |
| 
 | |
|   /// Check if any filters are active (for red dot indicator)
 | |
|   bool hasActiveFilters() {
 | |
|     return selectedUploadedBy.isNotEmpty ||
 | |
|         selectedCategory.isNotEmpty ||
 | |
|         selectedType.isNotEmpty ||
 | |
|         selectedTag.isNotEmpty;
 | |
|   }
 | |
| }
 |