199 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			199 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'package:flutter/material.dart';
 | |
| import 'package:get/get.dart';
 | |
| import 'package:marco/helpers/services/app_logger.dart';
 | |
| import 'package:marco/helpers/services/api_service.dart';
 | |
| import 'package:marco/model/project_model.dart';
 | |
| import 'package:marco/model/dailyTaskPlanning/daily_task_model.dart';
 | |
| import 'package:marco/model/dailyTaskPlanning/daily_progress_report_filter_response_model.dart';
 | |
| 
 | |
| class DailyTaskController extends GetxController {
 | |
|   List<ProjectModel> projects = [];
 | |
|   String? selectedProjectId;
 | |
| 
 | |
|   DateTime? startDateTask;
 | |
|   DateTime? endDateTask;
 | |
| 
 | |
|   List<TaskModel> dailyTasks = [];
 | |
|   final RxSet<String> expandedDates = <String>{}.obs;
 | |
| 
 | |
|   void toggleDate(String dateKey) {
 | |
|     if (expandedDates.contains(dateKey)) {
 | |
|       expandedDates.remove(dateKey);
 | |
|     } else {
 | |
|       expandedDates.add(dateKey);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   RxSet<String> selectedBuildings = <String>{}.obs;
 | |
|   RxSet<String> selectedFloors = <String>{}.obs;
 | |
|   RxSet<String> selectedActivities = <String>{}.obs;
 | |
|   RxSet<String> selectedServices = <String>{}.obs;
 | |
| 
 | |
|   RxBool isFilterLoading = false.obs;
 | |
|   RxBool isLoading = true.obs;
 | |
|   RxBool isLoadingMore = false.obs;
 | |
|   Map<String, List<TaskModel>> groupedDailyTasks = {};
 | |
|   // Pagination
 | |
|   int currentPage = 1;
 | |
|   int pageSize = 20;
 | |
|   bool hasMore = true;
 | |
|   @override
 | |
|   void onInit() {
 | |
|     super.onInit();
 | |
|     _initializeDefaults();
 | |
|   }
 | |
| 
 | |
|   void _initializeDefaults() {
 | |
|     _setDefaultDateRange();
 | |
|   }
 | |
| 
 | |
|   void _setDefaultDateRange() {
 | |
|     final today = DateTime.now();
 | |
|     startDateTask = today.subtract(const Duration(days: 7));
 | |
|     endDateTask = today;
 | |
| 
 | |
|     logSafe(
 | |
|       "Default date range set: $startDateTask to $endDateTask",
 | |
|       level: LogLevel.info,
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   void clearTaskFilters() {
 | |
|     selectedBuildings.clear();
 | |
|     selectedFloors.clear();
 | |
|     selectedActivities.clear();
 | |
|     selectedServices.clear();
 | |
|     startDateTask = null;
 | |
|     endDateTask = null;
 | |
|     update();
 | |
|   }
 | |
| 
 | |
|   Future<void> fetchTaskData(
 | |
|     String projectId, {
 | |
|     int pageNumber = 1,
 | |
|     int pageSize = 20,
 | |
|     bool isLoadMore = false,
 | |
|   }) async {
 | |
|     if (!isLoadMore) {
 | |
|       isLoading.value = true;
 | |
|       currentPage = 1;
 | |
|       hasMore = true;
 | |
|       groupedDailyTasks.clear();
 | |
|       dailyTasks.clear();
 | |
|     } else {
 | |
|       isLoadingMore.value = true;
 | |
|     }
 | |
| 
 | |
|     // Create the filter object
 | |
|     final filter = {
 | |
|       "buildingIds": selectedBuildings.toList(),
 | |
|       "floorIds": selectedFloors.toList(),
 | |
|       "activityIds": selectedActivities.toList(),
 | |
|       "serviceIds": selectedServices.toList(),
 | |
|       "dateFrom": startDateTask?.toIso8601String(),
 | |
|       "dateTo": endDateTask?.toIso8601String(),
 | |
|     };
 | |
| 
 | |
|     final response = await ApiService.getDailyTasks(
 | |
|       projectId,
 | |
|       filter: filter, 
 | |
|       pageNumber: pageNumber,
 | |
|       pageSize: pageSize,
 | |
|     );
 | |
| 
 | |
|     if (response != null && response.isNotEmpty) {
 | |
|       for (var task in response) {
 | |
|         final assignmentDateKey =
 | |
|             task.assignmentDate.toIso8601String().split('T')[0];
 | |
|         groupedDailyTasks.putIfAbsent(assignmentDateKey, () => []).add(task);
 | |
|       }
 | |
|       dailyTasks = groupedDailyTasks.values.expand((list) => list).toList();
 | |
|       currentPage = pageNumber;
 | |
|     } else {
 | |
|       hasMore = false;
 | |
|     }
 | |
| 
 | |
|     isLoading.value = false;
 | |
|     isLoadingMore.value = false;
 | |
| 
 | |
|     update();
 | |
|   }
 | |
| 
 | |
|   FilterData? taskFilterData;
 | |
| 
 | |
|   Future<void> fetchTaskFilter(String projectId) async {
 | |
|     isFilterLoading.value = true;
 | |
|     try {
 | |
|       final filterResponse = await ApiService.getDailyTaskFilter(projectId);
 | |
| 
 | |
|       if (filterResponse != null && filterResponse.success) {
 | |
|         taskFilterData =
 | |
|             filterResponse.data; // now taskFilterData is FilterData?
 | |
|         logSafe(
 | |
|           "Task filter fetched successfully. Buildings: ${taskFilterData?.buildings.length}, Floors: ${taskFilterData?.floors.length}",
 | |
|           level: LogLevel.info,
 | |
|         );
 | |
|       } else {
 | |
|         logSafe(
 | |
|           "Failed to fetch task filter for projectId: $projectId",
 | |
|           level: LogLevel.warning,
 | |
|         );
 | |
|       }
 | |
|     } catch (e, stack) {
 | |
|       logSafe("Exception in fetchTaskFilter: $e", level: LogLevel.error);
 | |
|       logSafe("StackTrace: $stack", level: LogLevel.debug);
 | |
|     } finally {
 | |
|       isFilterLoading.value = false;
 | |
|       update();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Future<void> selectDateRangeForTaskData(
 | |
|     BuildContext context,
 | |
|     DailyTaskController controller,
 | |
|   ) async {
 | |
|     final picked = await showDateRangePicker(
 | |
|       context: context,
 | |
|       firstDate: DateTime(2022),
 | |
|       lastDate: DateTime.now(),
 | |
|       initialDateRange: DateTimeRange(
 | |
|         start:
 | |
|             startDateTask ?? DateTime.now().subtract(const Duration(days: 7)),
 | |
|         end: endDateTask ?? DateTime.now(),
 | |
|       ),
 | |
|     );
 | |
| 
 | |
|     if (picked == null) {
 | |
|       logSafe("Date range picker cancelled by user.", level: LogLevel.debug);
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     startDateTask = picked.start;
 | |
|     endDateTask = picked.end;
 | |
| 
 | |
|     logSafe(
 | |
|       "Date range selected: $startDateTask to $endDateTask",
 | |
|       level: LogLevel.info,
 | |
|     );
 | |
| 
 | |
|     // ✅ Add null check before calling fetchTaskData
 | |
|     final projectId = controller.selectedProjectId;
 | |
|     if (projectId != null && projectId.isNotEmpty) {
 | |
|       await controller.fetchTaskData(projectId);
 | |
|     } else {
 | |
|       logSafe("Project ID is null or empty, skipping fetchTaskData",
 | |
|           level: LogLevel.warning);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   void refreshTasksFromNotification({
 | |
|     required String projectId,
 | |
|     required String taskAllocationId,
 | |
|   }) async {
 | |
|     // re-fetch tasks
 | |
|     await fetchTaskData(projectId);
 | |
| 
 | |
|     update(); // rebuilds UI
 | |
|   }
 | |
| }
 |