diff --git a/lib/controller/task_planning/daily_task_planning_controller.dart b/lib/controller/task_planning/daily_task_planning_controller.dart index 24217d5..a0d24df 100644 --- a/lib/controller/task_planning/daily_task_planning_controller.dart +++ b/lib/controller/task_planning/daily_task_planning_controller.dart @@ -127,14 +127,24 @@ class DailyTaskPlanningController extends GetxController { return; } - // Build only building-level data (floors empty). This enables lazy loading later. - dailyTasks = infraData.map((buildingJson) { + // Filter buildings with 0 planned & completed work + final filteredBuildings = infraData.where((b) { + final planned = (b['plannedWork'] as num?)?.toDouble() ?? 0; + final completed = (b['completedWork'] as num?)?.toDouble() ?? 0; + return planned > 0 || completed > 0; + }).toList(); + + dailyTasks = filteredBuildings.map((buildingJson) { final building = Building( id: buildingJson['id'], name: buildingJson['buildingName'], description: buildingJson['description'], - floors: [], // don't populate floors here - lazy load per-building + floors: [], + plannedWork: (buildingJson['plannedWork'] as num?)?.toDouble() ?? 0, + completedWork: + (buildingJson['completedWork'] as num?)?.toDouble() ?? 0, ); + return TaskPlanningDetailsModel( id: building.id, name: building.name, @@ -147,7 +157,6 @@ class DailyTaskPlanningController extends GetxController { ); }).toList(); - // Reset building loaded/loading maps because we replaced the list buildingLoadingStates.clear(); buildingsWithDetails.clear(); } catch (e, stack) { @@ -161,7 +170,8 @@ class DailyTaskPlanningController extends GetxController { /// Fetch full infra for a single building (floors, workAreas, workItems). /// Called lazily when user expands a building in the UI. - Future fetchBuildingInfra(String buildingId, String projectId, String? serviceId) async { + Future fetchBuildingInfra( + String buildingId, String projectId, String? serviceId) async { if (buildingId.isEmpty) return; // mark loading @@ -171,7 +181,8 @@ class DailyTaskPlanningController extends GetxController { try { // Re-use getInfraDetails and find the building entry for the requested buildingId - final infraResponse = await ApiService.getInfraDetails(projectId, serviceId: serviceId); + final infraResponse = + await ApiService.getInfraDetails(projectId, serviceId: serviceId); final infraData = infraResponse?['data'] as List? ?? []; final buildingJson = infraData.firstWhere( @@ -180,7 +191,8 @@ class DailyTaskPlanningController extends GetxController { ); if (buildingJson == null) { - logSafe("Building $buildingId not found in infra response", level: LogLevel.warning); + logSafe("Building $buildingId not found in infra response", + level: LogLevel.warning); return; } @@ -189,26 +201,31 @@ class DailyTaskPlanningController extends GetxController { id: buildingJson['id'], name: buildingJson['buildingName'], description: buildingJson['description'], - floors: (buildingJson['floors'] as List? ?? []).map((floorJson) { + floors: + (buildingJson['floors'] as List? ?? []).map((floorJson) { return Floor( id: floorJson['id'], floorName: floorJson['floorName'], - workAreas: (floorJson['workAreas'] as List? ?? []).map((areaJson) { + workAreas: (floorJson['workAreas'] as List? ?? []) + .map((areaJson) { return WorkArea( id: areaJson['id'], areaName: areaJson['areaName'], - workItems: [], // will populate below + workItems: [], // will populate later ); }).toList(), ); }).toList(), + plannedWork: (buildingJson['plannedWork'] as num?)?.toDouble() ?? 0, + completedWork: (buildingJson['completedWork'] as num?)?.toDouble() ?? 0, ); // For each workArea, fetch its work items and populate - await Future.wait(building.floors.expand((f) => f.workAreas).map((area) async { + await Future.wait( + building.floors.expand((f) => f.workAreas).map((area) async { try { - final taskResponse = - await ApiService.getWorkItemsByWorkArea(area.id, serviceId: serviceId); + final taskResponse = await ApiService.getWorkItemsByWorkArea(area.id, + serviceId: serviceId); final taskData = taskResponse?['data'] as List? ?? []; area.workItems.addAll(taskData.map((taskJson) => WorkItemWrapper( workItemId: taskJson['id'], @@ -218,13 +235,18 @@ class DailyTaskPlanningController extends GetxController { ? ActivityMaster.fromJson(taskJson['activityMaster']) : null, workCategoryMaster: taskJson['workCategoryMaster'] != null - ? WorkCategoryMaster.fromJson(taskJson['workCategoryMaster']) + ? WorkCategoryMaster.fromJson( + taskJson['workCategoryMaster']) : null, plannedWork: (taskJson['plannedWork'] as num?)?.toDouble(), - completedWork: (taskJson['completedWork'] as num?)?.toDouble(), - todaysAssigned: (taskJson['todaysAssigned'] as num?)?.toDouble(), + completedWork: + (taskJson['completedWork'] as num?)?.toDouble(), + todaysAssigned: + (taskJson['todaysAssigned'] as num?)?.toDouble(), description: taskJson['description'] as String?, - taskDate: taskJson['taskDate'] != null ? DateTime.tryParse(taskJson['taskDate']) : null, + taskDate: taskJson['taskDate'] != null + ? DateTime.tryParse(taskJson['taskDate']) + : null, ), ))); } catch (e, stack) { @@ -236,7 +258,8 @@ class DailyTaskPlanningController extends GetxController { // Merge/replace the building into dailyTasks bool merged = false; for (var t in dailyTasks) { - final idx = t.buildings.indexWhere((b) => b.id.toString() == building.id.toString()); + final idx = t.buildings + .indexWhere((b) => b.id.toString() == building.id.toString()); if (idx != -1) { t.buildings[idx] = building; merged = true; @@ -284,7 +307,8 @@ class DailyTaskPlanningController extends GetxController { ); if (response != null && response.isNotEmpty) { - employees.assignAll(response.map((json) => EmployeeModel.fromJson(json))); + employees + .assignAll(response.map((json) => EmployeeModel.fromJson(json))); if (serviceId == null && organizationId == null) { allEmployeesCache = List.from(employees); @@ -292,12 +316,14 @@ class DailyTaskPlanningController extends GetxController { final currentEmployeeIds = employees.map((e) => e.id).toSet(); - uploadingStates.removeWhere((key, _) => !currentEmployeeIds.contains(key)); + uploadingStates + .removeWhere((key, _) => !currentEmployeeIds.contains(key)); employees.forEach((emp) { uploadingStates.putIfAbsent(emp.id, () => false.obs); }); - selectedEmployees.removeWhere((e) => !currentEmployeeIds.contains(e.id)); + selectedEmployees + .removeWhere((e) => !currentEmployeeIds.contains(e.id)); logSafe("Employees fetched: ${employees.length}", level: LogLevel.info); } else { @@ -312,13 +338,17 @@ class DailyTaskPlanningController extends GetxController { ); } } catch (e, stack) { - logSafe("Error fetching employees", level: LogLevel.error, error: e, stackTrace: stack); + logSafe("Error fetching employees", + level: LogLevel.error, error: e, stackTrace: stack); - if (serviceId == null && organizationId == null && allEmployeesCache.isNotEmpty) { + if (serviceId == null && + organizationId == null && + allEmployeesCache.isNotEmpty) { employees.assignAll(allEmployeesCache); final cachedEmployeeIds = employees.map((e) => e.id).toSet(); - uploadingStates.removeWhere((key, _) => !cachedEmployeeIds.contains(key)); + uploadingStates + .removeWhere((key, _) => !cachedEmployeeIds.contains(key)); employees.forEach((emp) { uploadingStates.putIfAbsent(emp.id, () => false.obs); }); diff --git a/lib/model/dailyTaskPlanning/daily_task_planning_model.dart b/lib/model/dailyTaskPlanning/daily_task_planning_model.dart index 7609903..b9f73a5 100644 --- a/lib/model/dailyTaskPlanning/daily_task_planning_model.dart +++ b/lib/model/dailyTaskPlanning/daily_task_planning_model.dart @@ -41,20 +41,28 @@ class Building { final String name; final String description; final List floors; + final double plannedWork; + final double completedWork; Building({ required this.id, required this.name, required this.description, required this.floors, + required this.plannedWork, + required this.completedWork, }); factory Building.fromJson(Map json) { return Building( id: json['id'], - name: json['name'], - description: json['description'], - floors: (json['floors'] as List).map((f) => Floor.fromJson(f)).toList(), + name: json['buildingName'] ?? json['name'], + description: json['description'] ?? '', + floors: + (json['floors'] as List?)?.map((f) => Floor.fromJson(f)).toList() ?? + [], + plannedWork: (json['plannedWork'] as num?)?.toDouble() ?? 0, + completedWork: (json['completedWork'] as num?)?.toDouble() ?? 0, ); } } @@ -177,7 +185,7 @@ class WorkItem { : null, todaysAssigned: json['todaysAssigned'] != null ? (json['todaysAssigned'] as num).toDouble() - : null, + : null, description: json['description'] as String?, taskDate: json['taskDate'] != null ? DateTime.tryParse(json['taskDate']) : null, diff --git a/lib/view/taskPlanning/daily_task_planning.dart b/lib/view/taskPlanning/daily_task_planning.dart index b5d13a4..db3c7d2 100644 --- a/lib/view/taskPlanning/daily_task_planning.dart +++ b/lib/view/taskPlanning/daily_task_planning.dart @@ -223,7 +223,13 @@ class _DailyTaskPlanningScreenState extends State return StatefulBuilder(builder: (context, setMainState) { // Show all buildings (they may or may not have floors loaded yet) - final buildings = dailyTasks.expand((task) => task.buildings).toList(); + + final buildings = dailyTasks + .expand((task) => task.buildings) + .where((building) => + (building.plannedWork ?? 0) > 0 || + (building.completedWork ?? 0) > 0) + .toList(); if (buildings.isEmpty) { return Center(