fixed the no data building are dispalyed

This commit is contained in:
Vaibhav Surve 2025-11-11 15:27:19 +05:30
parent fe950c5b07
commit 7f0c4d075d
3 changed files with 73 additions and 29 deletions

View File

@ -127,14 +127,24 @@ class DailyTaskPlanningController extends GetxController {
return; return;
} }
// Build only building-level data (floors empty). This enables lazy loading later. // Filter buildings with 0 planned & completed work
dailyTasks = infraData.map((buildingJson) { 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( final building = Building(
id: buildingJson['id'], id: buildingJson['id'],
name: buildingJson['buildingName'], name: buildingJson['buildingName'],
description: buildingJson['description'], 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( return TaskPlanningDetailsModel(
id: building.id, id: building.id,
name: building.name, name: building.name,
@ -147,7 +157,6 @@ class DailyTaskPlanningController extends GetxController {
); );
}).toList(); }).toList();
// Reset building loaded/loading maps because we replaced the list
buildingLoadingStates.clear(); buildingLoadingStates.clear();
buildingsWithDetails.clear(); buildingsWithDetails.clear();
} catch (e, stack) { } catch (e, stack) {
@ -161,7 +170,8 @@ class DailyTaskPlanningController extends GetxController {
/// Fetch full infra for a single building (floors, workAreas, workItems). /// Fetch full infra for a single building (floors, workAreas, workItems).
/// Called lazily when user expands a building in the UI. /// Called lazily when user expands a building in the UI.
Future<void> fetchBuildingInfra(String buildingId, String projectId, String? serviceId) async { Future<void> fetchBuildingInfra(
String buildingId, String projectId, String? serviceId) async {
if (buildingId.isEmpty) return; if (buildingId.isEmpty) return;
// mark loading // mark loading
@ -171,7 +181,8 @@ class DailyTaskPlanningController extends GetxController {
try { try {
// Re-use getInfraDetails and find the building entry for the requested buildingId // 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<dynamic>? ?? []; final infraData = infraResponse?['data'] as List<dynamic>? ?? [];
final buildingJson = infraData.firstWhere( final buildingJson = infraData.firstWhere(
@ -180,7 +191,8 @@ class DailyTaskPlanningController extends GetxController {
); );
if (buildingJson == null) { 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; return;
} }
@ -189,26 +201,31 @@ class DailyTaskPlanningController extends GetxController {
id: buildingJson['id'], id: buildingJson['id'],
name: buildingJson['buildingName'], name: buildingJson['buildingName'],
description: buildingJson['description'], description: buildingJson['description'],
floors: (buildingJson['floors'] as List<dynamic>? ?? []).map((floorJson) { floors:
(buildingJson['floors'] as List<dynamic>? ?? []).map((floorJson) {
return Floor( return Floor(
id: floorJson['id'], id: floorJson['id'],
floorName: floorJson['floorName'], floorName: floorJson['floorName'],
workAreas: (floorJson['workAreas'] as List<dynamic>? ?? []).map((areaJson) { workAreas: (floorJson['workAreas'] as List<dynamic>? ?? [])
.map((areaJson) {
return WorkArea( return WorkArea(
id: areaJson['id'], id: areaJson['id'],
areaName: areaJson['areaName'], areaName: areaJson['areaName'],
workItems: [], // will populate below workItems: [], // will populate later
); );
}).toList(), }).toList(),
); );
}).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 // 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 { try {
final taskResponse = final taskResponse = await ApiService.getWorkItemsByWorkArea(area.id,
await ApiService.getWorkItemsByWorkArea(area.id, serviceId: serviceId); serviceId: serviceId);
final taskData = taskResponse?['data'] as List<dynamic>? ?? []; final taskData = taskResponse?['data'] as List<dynamic>? ?? [];
area.workItems.addAll(taskData.map((taskJson) => WorkItemWrapper( area.workItems.addAll(taskData.map((taskJson) => WorkItemWrapper(
workItemId: taskJson['id'], workItemId: taskJson['id'],
@ -218,13 +235,18 @@ class DailyTaskPlanningController extends GetxController {
? ActivityMaster.fromJson(taskJson['activityMaster']) ? ActivityMaster.fromJson(taskJson['activityMaster'])
: null, : null,
workCategoryMaster: taskJson['workCategoryMaster'] != null workCategoryMaster: taskJson['workCategoryMaster'] != null
? WorkCategoryMaster.fromJson(taskJson['workCategoryMaster']) ? WorkCategoryMaster.fromJson(
taskJson['workCategoryMaster'])
: null, : null,
plannedWork: (taskJson['plannedWork'] as num?)?.toDouble(), plannedWork: (taskJson['plannedWork'] as num?)?.toDouble(),
completedWork: (taskJson['completedWork'] as num?)?.toDouble(), completedWork:
todaysAssigned: (taskJson['todaysAssigned'] as num?)?.toDouble(), (taskJson['completedWork'] as num?)?.toDouble(),
todaysAssigned:
(taskJson['todaysAssigned'] as num?)?.toDouble(),
description: taskJson['description'] as String?, 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) { } catch (e, stack) {
@ -236,7 +258,8 @@ class DailyTaskPlanningController extends GetxController {
// Merge/replace the building into dailyTasks // Merge/replace the building into dailyTasks
bool merged = false; bool merged = false;
for (var t in dailyTasks) { 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) { if (idx != -1) {
t.buildings[idx] = building; t.buildings[idx] = building;
merged = true; merged = true;
@ -284,7 +307,8 @@ class DailyTaskPlanningController extends GetxController {
); );
if (response != null && response.isNotEmpty) { 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) { if (serviceId == null && organizationId == null) {
allEmployeesCache = List.from(employees); allEmployeesCache = List.from(employees);
@ -292,12 +316,14 @@ class DailyTaskPlanningController extends GetxController {
final currentEmployeeIds = employees.map((e) => e.id).toSet(); final currentEmployeeIds = employees.map((e) => e.id).toSet();
uploadingStates.removeWhere((key, _) => !currentEmployeeIds.contains(key)); uploadingStates
.removeWhere((key, _) => !currentEmployeeIds.contains(key));
employees.forEach((emp) { employees.forEach((emp) {
uploadingStates.putIfAbsent(emp.id, () => false.obs); 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); logSafe("Employees fetched: ${employees.length}", level: LogLevel.info);
} else { } else {
@ -312,13 +338,17 @@ class DailyTaskPlanningController extends GetxController {
); );
} }
} catch (e, stack) { } 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); employees.assignAll(allEmployeesCache);
final cachedEmployeeIds = employees.map((e) => e.id).toSet(); final cachedEmployeeIds = employees.map((e) => e.id).toSet();
uploadingStates.removeWhere((key, _) => !cachedEmployeeIds.contains(key)); uploadingStates
.removeWhere((key, _) => !cachedEmployeeIds.contains(key));
employees.forEach((emp) { employees.forEach((emp) {
uploadingStates.putIfAbsent(emp.id, () => false.obs); uploadingStates.putIfAbsent(emp.id, () => false.obs);
}); });

View File

@ -41,20 +41,28 @@ class Building {
final String name; final String name;
final String description; final String description;
final List<Floor> floors; final List<Floor> floors;
final double plannedWork;
final double completedWork;
Building({ Building({
required this.id, required this.id,
required this.name, required this.name,
required this.description, required this.description,
required this.floors, required this.floors,
required this.plannedWork,
required this.completedWork,
}); });
factory Building.fromJson(Map<String, dynamic> json) { factory Building.fromJson(Map<String, dynamic> json) {
return Building( return Building(
id: json['id'], id: json['id'],
name: json['name'], name: json['buildingName'] ?? json['name'],
description: json['description'], description: json['description'] ?? '',
floors: (json['floors'] as List).map((f) => Floor.fromJson(f)).toList(), 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, : null,
todaysAssigned: json['todaysAssigned'] != null todaysAssigned: json['todaysAssigned'] != null
? (json['todaysAssigned'] as num).toDouble() ? (json['todaysAssigned'] as num).toDouble()
: null, : null,
description: json['description'] as String?, description: json['description'] as String?,
taskDate: taskDate:
json['taskDate'] != null ? DateTime.tryParse(json['taskDate']) : null, json['taskDate'] != null ? DateTime.tryParse(json['taskDate']) : null,

View File

@ -223,7 +223,13 @@ class _DailyTaskPlanningScreenState extends State<DailyTaskPlanningScreen>
return StatefulBuilder(builder: (context, setMainState) { return StatefulBuilder(builder: (context, setMainState) {
// Show all buildings (they may or may not have floors loaded yet) // 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) { if (buildings.isEmpty) {
return Center( return Center(