marco.pms.mobileapp/lib/controller/document/user_document_controller.dart

214 lines
5.7 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 ====================
final isLoading = false.obs;
final documents = <DocumentItem>[].obs;
final filters = Rxn<DocumentFiltersData>();
// Selected filters (multi-select)
final selectedUploadedBy = <String>[].obs;
final selectedCategory = <String>[].obs;
final selectedType = <String>[].obs;
final selectedTag = <String>[].obs;
// Pagination
final pageNumber = 1.obs;
final pageSize = 20;
final hasMore = true.obs;
// Error handling
final errorMessage = ''.obs;
// Preferences
final showInactive = false.obs;
// Search
final searchQuery = ''.obs;
final searchController = TextEditingController();
// Additional filters
final isUploadedAt = true.obs;
final isVerified = RxnBool();
final startDate = Rxn<String>();
final endDate = Rxn<String>();
// ==================== Lifecycle ====================
@override
void onClose() {
// Don't dispose searchController here - it's managed by the page
super.onClose();
}
// ==================== API Methods ====================
/// Fetch document filters for entity
Future<void> fetchFilters(String entityTypeId) async {
try {
final response = await ApiService.getDocumentFilters(entityTypeId);
if (response != null && response.success) {
filters.value = response.data;
} else {
errorMessage.value = response?.message ?? 'Failed to fetch filters';
_showError('Failed to load filters');
}
} catch (e) {
errorMessage.value = 'Error fetching filters: $e';
_showError('Error loading filters');
debugPrint('❌ Error fetching filters: $e');
}
}
/// 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) {
// Refresh list after state change
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';
debugPrint('❌ Error toggling document state: $e');
return false;
} finally {
isLoading.value = false;
}
}
/// Fetch documents for entity with pagination
Future<void> fetchDocuments({
required String entityTypeId,
required String entityId,
String? filter,
String? searchString,
bool reset = false,
}) async {
try {
// Reset pagination if needed
if (reset) {
pageNumber.value = 1;
documents.clear();
hasMore.value = true;
}
// Don't fetch if no more data
if (!hasMore.value && !reset) return;
// Prevent duplicate requests
if (isLoading.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;
}
errorMessage.value = '';
} else {
errorMessage.value = response?.message ?? 'Failed to fetch documents';
if (documents.isEmpty) {
_showError('Failed to load documents');
}
}
} catch (e) {
errorMessage.value = 'Error fetching documents: $e';
if (documents.isEmpty) {
_showError('Error loading documents');
}
debugPrint('❌ Error fetching documents: $e');
} finally {
isLoading.value = false;
}
}
// ==================== Helper Methods ====================
/// Clear all 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
bool hasActiveFilters() {
return selectedUploadedBy.isNotEmpty ||
selectedCategory.isNotEmpty ||
selectedType.isNotEmpty ||
selectedTag.isNotEmpty ||
startDate.value != null ||
endDate.value != null ||
isVerified.value != null;
}
/// Show error message
void _showError(String message) {
Get.snackbar(
'Error',
message,
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.red.shade100,
colorText: Colors.red.shade900,
margin: const EdgeInsets.all(16),
borderRadius: 8,
duration: const Duration(seconds: 3),
);
}
/// Reset controller state
void reset() {
documents.clear();
clearFilters();
searchController.clear();
searchQuery.value = '';
pageNumber.value = 1;
hasMore.value = true;
showInactive.value = false;
errorMessage.value = '';
}
}