Compare commits
3 Commits
ae7ce851ee
...
9362945d60
Author | SHA1 | Date | |
---|---|---|---|
9362945d60 | |||
b5e9c7b6a3 | |||
04cbdab277 |
@ -18,7 +18,6 @@ class DailyTaskPlanningController extends GetxController {
|
||||
MyFormValidator basicValidator = MyFormValidator();
|
||||
List<Map<String, dynamic>> roles = [];
|
||||
RxBool isAssigningTask = false.obs;
|
||||
|
||||
RxnString selectedRoleId = RxnString();
|
||||
RxBool isLoading = false.obs;
|
||||
|
||||
@ -50,18 +49,12 @@ class DailyTaskPlanningController extends GetxController {
|
||||
final selected =
|
||||
employees.where((e) => uploadingStates[e.id]?.value == true).toList();
|
||||
selectedEmployees.value = selected;
|
||||
logSafe(
|
||||
"Updated selected employees",
|
||||
level: LogLevel.debug,
|
||||
);
|
||||
logSafe("Updated selected employees", level: LogLevel.debug);
|
||||
}
|
||||
|
||||
void onRoleSelected(String? roleId) {
|
||||
selectedRoleId.value = roleId;
|
||||
logSafe(
|
||||
"Role selected",
|
||||
level: LogLevel.info,
|
||||
);
|
||||
logSafe("Role selected", level: LogLevel.info);
|
||||
}
|
||||
|
||||
Future<void> fetchRoles() async {
|
||||
@ -94,7 +87,7 @@ class DailyTaskPlanningController extends GetxController {
|
||||
assignmentDate: assignmentDate,
|
||||
);
|
||||
|
||||
isAssigningTask.value = false;
|
||||
isAssigningTask.value = false;
|
||||
|
||||
if (response == true) {
|
||||
logSafe("Task assigned successfully", level: LogLevel.info);
|
||||
@ -137,6 +130,7 @@ class DailyTaskPlanningController extends GetxController {
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetch Infra details and then tasks per work area
|
||||
Future<void> fetchTaskData(String? projectId) async {
|
||||
if (projectId == null) {
|
||||
logSafe("Project ID is null", level: LogLevel.warning);
|
||||
@ -145,20 +139,89 @@ class DailyTaskPlanningController extends GetxController {
|
||||
|
||||
isLoading.value = true;
|
||||
try {
|
||||
final response = await ApiService.getDailyTasksDetails(projectId);
|
||||
final data = response?['data'];
|
||||
if (data != null) {
|
||||
dailyTasks = [TaskPlanningDetailsModel.fromJson(data)];
|
||||
logSafe(
|
||||
"Daily task Planning Details fetched",
|
||||
level: LogLevel.info,
|
||||
);
|
||||
} else {
|
||||
logSafe("Data field is null", level: LogLevel.warning);
|
||||
final infraResponse = await ApiService.getInfraDetails(projectId);
|
||||
final infraData = infraResponse?['data'] as List<dynamic>?;
|
||||
|
||||
if (infraData == null || infraData.isEmpty) {
|
||||
logSafe("No infra data found for project $projectId",
|
||||
level: LogLevel.warning);
|
||||
dailyTasks = [];
|
||||
return;
|
||||
}
|
||||
|
||||
// Map infra to dailyTasks structure
|
||||
dailyTasks = infraData.map((buildingJson) {
|
||||
final building = Building(
|
||||
id: buildingJson['id'],
|
||||
name: buildingJson['buildingName'],
|
||||
description: buildingJson['description'],
|
||||
floors: (buildingJson['floors'] as List<dynamic>).map((floorJson) {
|
||||
return Floor(
|
||||
id: floorJson['id'],
|
||||
floorName: floorJson['floorName'],
|
||||
workAreas: (floorJson['workAreas'] as List<dynamic>).map((areaJson) {
|
||||
return WorkArea(
|
||||
id: areaJson['id'],
|
||||
areaName: areaJson['areaName'],
|
||||
workItems: [], // Initially empty, will fill after tasks API
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
|
||||
return TaskPlanningDetailsModel(
|
||||
id: building.id,
|
||||
name: building.name,
|
||||
projectAddress: "",
|
||||
contactPerson: "",
|
||||
startDate: DateTime.now(),
|
||||
endDate: DateTime.now(),
|
||||
projectStatusId: "",
|
||||
buildings: [building],
|
||||
);
|
||||
}).toList();
|
||||
|
||||
// Fetch tasks for each work area
|
||||
await Future.wait(dailyTasks.expand((task) => task.buildings)
|
||||
.expand((b) => b.floors)
|
||||
.expand((f) => f.workAreas)
|
||||
.map((area) async {
|
||||
try {
|
||||
final taskResponse = await ApiService.getWorkItemsByWorkArea(area.id);
|
||||
final taskData = taskResponse?['data'] as List<dynamic>? ?? [];
|
||||
|
||||
area.workItems.addAll(taskData.map((taskJson) {
|
||||
return WorkItemWrapper(
|
||||
workItemId: taskJson['id'],
|
||||
workItem: WorkItem(
|
||||
id: taskJson['id'],
|
||||
activityMaster: taskJson['activityMaster'] != null
|
||||
? ActivityMaster.fromJson(taskJson['activityMaster'])
|
||||
: null,
|
||||
workCategoryMaster: taskJson['workCategoryMaster'] != null
|
||||
? WorkCategoryMaster.fromJson(taskJson['workCategoryMaster'])
|
||||
: null,
|
||||
plannedWork: (taskJson['plannedWork'] 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,
|
||||
),
|
||||
);
|
||||
}));
|
||||
} catch (e, stack) {
|
||||
logSafe("Error fetching tasks for work area ${area.id}",
|
||||
level: LogLevel.error, error: e, stackTrace: stack);
|
||||
}
|
||||
}));
|
||||
|
||||
logSafe("Fetched infra and tasks for project $projectId",
|
||||
level: LogLevel.info);
|
||||
} catch (e, stack) {
|
||||
logSafe("Error fetching daily task data",
|
||||
level: LogLevel.error, error: e, stackTrace: stack);
|
||||
logSafe("Error fetching daily task data", level: LogLevel.error, error: e, stackTrace: stack);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
update();
|
||||
|
@ -1,6 +1,6 @@
|
||||
class ApiEndpoints {
|
||||
// static const String baseUrl = "https://stageapi.marcoaiot.com/api";
|
||||
static const String baseUrl = "https://api.marcoaiot.com/api";
|
||||
static const String baseUrl = "https://stageapi.marcoaiot.com/api";
|
||||
// static const String baseUrl = "https://api.marcoaiot.com/api";
|
||||
// static const String baseUrl = "https://devapi.marcoaiot.com/api";
|
||||
|
||||
// Dashboard Module API Endpoints
|
||||
|
@ -1880,7 +1880,7 @@ class ApiService {
|
||||
_getRequest(ApiEndpoints.getRoles).then(
|
||||
(res) => res != null ? _parseResponse(res, label: 'Roles') : null);
|
||||
static Future<Map<String, dynamic>?> createEmployee({
|
||||
String? id, // Optional, for editing
|
||||
String? id,
|
||||
required String firstName,
|
||||
required String lastName,
|
||||
required String phoneNumber,
|
||||
@ -1889,7 +1889,7 @@ class ApiService {
|
||||
required String joiningDate,
|
||||
}) async {
|
||||
final body = {
|
||||
if (id != null) "id": id, // Include id only if editing
|
||||
if (id != null) "id": id,
|
||||
"firstName": firstName,
|
||||
"lastName": lastName,
|
||||
"phoneNumber": phoneNumber,
|
||||
@ -1991,14 +1991,35 @@ class ApiService {
|
||||
return response.statusCode == 200 && json['success'] == true;
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>?> getDailyTasksDetails(
|
||||
String projectId) async {
|
||||
final url = "${ApiEndpoints.dailyTaskDetails}/$projectId";
|
||||
final response = await _getRequest(url);
|
||||
return response != null
|
||||
? _parseResponseForAllData(response, label: 'Daily Task Details')
|
||||
as Map<String, dynamic>?
|
||||
: null;
|
||||
/// Fetch infra details for a given project
|
||||
static Future<Map<String, dynamic>?> getInfraDetails(String projectId) async {
|
||||
final endpoint = "/project/infra-details/$projectId";
|
||||
|
||||
final res = await _getRequest(endpoint);
|
||||
if (res == null) {
|
||||
logSafe('Infra Details API returned null');
|
||||
return null;
|
||||
}
|
||||
|
||||
logSafe('Infra Details raw response: ${res.body}');
|
||||
return _parseResponseForAllData(res, label: 'Infra Details')
|
||||
as Map<String, dynamic>?;
|
||||
}
|
||||
|
||||
/// Fetch work items for a given work area
|
||||
static Future<Map<String, dynamic>?> getWorkItemsByWorkArea(
|
||||
String workAreaId) async {
|
||||
final endpoint = "/project/tasks/$workAreaId";
|
||||
|
||||
final res = await _getRequest(endpoint);
|
||||
if (res == null) {
|
||||
logSafe('Work Items API returned null');
|
||||
return null;
|
||||
}
|
||||
|
||||
logSafe('Work Items raw response: ${res.body}');
|
||||
return _parseResponseForAllData(res, label: 'Work Items')
|
||||
as Map<String, dynamic>?;
|
||||
}
|
||||
|
||||
static Future<bool> assignDailyTask({
|
||||
|
@ -68,6 +68,10 @@ class NotificationActionHandler {
|
||||
_handleDashboardUpdate(data);
|
||||
}
|
||||
break;
|
||||
case 'Team_Modified':
|
||||
// Call method to handle team modifications and dashboard update
|
||||
_handleDashboardUpdate(data);
|
||||
break;
|
||||
|
||||
/// 🔹 Tasks
|
||||
case 'Report_Task':
|
||||
@ -270,7 +274,6 @@ class NotificationActionHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/// ---------------------- DIRECTORY HANDLERS ----------------------
|
||||
/// ---------------------- DIRECTORY HANDLERS ----------------------
|
||||
static void _handleContactModified(Map<String, dynamic> data) {
|
||||
final contactId = data['ContactId'];
|
||||
@ -299,8 +302,6 @@ class NotificationActionHandler {
|
||||
}
|
||||
|
||||
static void _handleContactNoteModified(Map<String, dynamic> data) {
|
||||
final contactId = data['ContactId'];
|
||||
|
||||
// Refresh both contacts and notes when a note is modified
|
||||
_handleContactModified(data);
|
||||
}
|
||||
@ -330,14 +331,38 @@ class NotificationActionHandler {
|
||||
case 'attendance_updated':
|
||||
await controller.fetchRoleWiseAttendance();
|
||||
break;
|
||||
|
||||
case 'task_updated':
|
||||
await controller.fetchDashboardTasks(
|
||||
projectId:
|
||||
controller.projectController.selectedProjectId.value);
|
||||
projectId: controller.projectController.selectedProjectId.value,
|
||||
);
|
||||
break;
|
||||
|
||||
case 'project_progress_update':
|
||||
await controller.fetchProjectProgress();
|
||||
break;
|
||||
|
||||
case 'Employee_Suspend':
|
||||
final currentProjectId =
|
||||
controller.projectController.selectedProjectId.value;
|
||||
final projectIdsString = data['ProjectIds'] ?? '';
|
||||
|
||||
// Convert comma-separated string to List<String>
|
||||
final notificationProjectIds =
|
||||
projectIdsString.split(',').map((e) => e.trim()).toList();
|
||||
|
||||
// Refresh only if current project ID is in the list
|
||||
if (notificationProjectIds.contains(currentProjectId)) {
|
||||
await controller.fetchDashboardTeams(projectId: currentProjectId);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Team_Modified':
|
||||
final projectId = data['ProjectId'] ??
|
||||
controller.projectController.selectedProjectId.value;
|
||||
await controller.fetchDashboardTeams(projectId: projectId);
|
||||
break;
|
||||
|
||||
case 'full_dashboard_refresh':
|
||||
default:
|
||||
await controller.refreshDashboard();
|
||||
|
@ -129,6 +129,7 @@ class WorkItem {
|
||||
final WorkCategoryMaster? workCategoryMaster;
|
||||
final double? plannedWork;
|
||||
final double? completedWork;
|
||||
final String? description;
|
||||
final double? todaysAssigned;
|
||||
final DateTime? taskDate;
|
||||
final String? tenantId;
|
||||
@ -142,6 +143,7 @@ class WorkItem {
|
||||
this.workArea,
|
||||
this.activityMaster,
|
||||
this.workCategoryMaster,
|
||||
this.description,
|
||||
this.plannedWork,
|
||||
this.completedWork,
|
||||
this.todaysAssigned,
|
||||
@ -175,7 +177,8 @@ class WorkItem {
|
||||
: null,
|
||||
todaysAssigned: json['todaysAssigned'] != null
|
||||
? (json['todaysAssigned'] as num).toDouble()
|
||||
: null, // ✅ added parsing
|
||||
: null,
|
||||
description: json['description'] as String?,
|
||||
taskDate:
|
||||
json['taskDate'] != null ? DateTime.tryParse(json['taskDate']) : null,
|
||||
tenantId: json['tenantId'] as String?,
|
||||
|
@ -116,7 +116,7 @@ class _AttendanceLogsTabState extends State<AttendanceLogsTab> {
|
||||
final showPendingOnly = widget.controller.showPendingOnly.value;
|
||||
final filteredLogs = showPendingOnly
|
||||
? allLogs
|
||||
.where((emp) => emp.activity == 1 || emp.activity == 2)
|
||||
.where((emp) => emp.activity == 1 )
|
||||
.toList()
|
||||
: allLogs;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user