marco.pms.mobileapp/lib/helpers/services/notification_action_handler.dart
Vaibhav Surve a154872649 feat: Implement daily task planning and progress reporting features
- Added TaskListModel for managing daily tasks with JSON parsing.
- Introduced WorkStatusResponseModel and WorkStatus for handling work status data.
- Created MenuResponse and MenuItem models for dynamic menu management.
- Updated routes to reflect correct naming conventions for task planning screens.
- Enhanced DashboardScreen to include dynamic menu functionality and improved task statistics display.
- Developed DailyProgressReportScreen for displaying daily progress reports with filtering options.
- Implemented DailyTaskPlanningScreen for planning daily tasks with detailed views and actions.
- Refactored left navigation bar to align with updated task planning routes.
2025-08-28 14:48:05 +05:30

184 lines
5.8 KiB
Dart
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:get/get.dart';
import 'package:logger/logger.dart';
import 'package:marco/controller/dashboard/attendance_screen_controller.dart';
import 'package:marco/controller/dashboard/daily_task_controller.dart';
import 'package:marco/controller/task_Planning/daily_task_Planning_controller.dart';
import 'package:marco/controller/expense/expense_screen_controller.dart';
import 'package:marco/controller/expense/expense_detail_controller.dart';
/// Handles incoming FCM notification actions and updates UI/controllers.
class NotificationActionHandler {
static final Logger _logger = Logger();
/// Main entry point — call this for any notification `data` map.
static void handle(Map<String, dynamic> data) {
_logger.i('📲 Handling notification action: $data');
if (data.isEmpty) {
_logger.w('⚠️ Empty notification data received.');
return;
}
final type = data['type'];
final action = data['Action'];
final keyword = data['Keyword'];
if (type != null) {
_handleByType(type, data);
} else if (keyword != null) {
_handleByKeyword(keyword, action, data);
} else {
_logger.w('⚠️ Unhandled notification: $data');
}
}
/// Handle notification if identified by `type`
static void _handleByType(String type, Map<String, dynamic> data) {
switch (type) {
case 'expense_updated':
// No specific handler yet
break;
case 'attendance_updated':
_handleAttendanceUpdated(data);
break;
default:
_logger.w('⚠️ Unknown notification type: $type');
}
}
/// Handle notification if identified by `keyword`
static void _handleByKeyword(
String keyword, String? action, Map<String, dynamic> data) {
switch (keyword) {
case 'Attendance':
if (_isAttendanceAction(action)) {
_handleAttendanceUpdated(data);
}
break;
case 'Report_Task':
_handleTaskUpdated(data, isComment: false);
break;
case 'Task_Comment':
_handleTaskUpdated(data, isComment: true);
break;
case 'Expenses_Modified':
_handleExpenseUpdated(data);
break;
// ✅ New cases
case 'Task_Modified':
case 'WorkArea_Modified':
case 'Floor_Modified':
case 'Building_Modified':
_handleTaskPlanningUpdated(data);
break;
default:
_logger.w('⚠️ Unhandled notification keyword: $keyword');
}
}
static void _handleTaskPlanningUpdated(Map<String, dynamic> data) {
final projectId = data['ProjectId'];
if (projectId == null) {
_logger.w("⚠️ TaskPlanning update received without ProjectId: $data");
return;
}
_safeControllerUpdate<DailyTaskPlanningController>(
onFound: (controller) {
controller.fetchTaskData(projectId);
},
notFoundMessage:
'⚠️ DailyTaskPlanningController not found, cannot refresh.',
successMessage:
'✅ DailyTaskPlanningController refreshed from notification.',
);
}
/// Validates the set of allowed Attendance actions
static bool _isAttendanceAction(String? action) {
const validActions = {
'CHECK_IN',
'CHECK_OUT',
'REQUEST_REGULARIZE',
'REQUEST_DELETE',
'REGULARIZE',
'REGULARIZE_REJECT'
};
return validActions.contains(action);
}
static void _handleExpenseUpdated(Map<String, dynamic> data) {
final expenseId = data['ExpenseId'];
if (expenseId == null) {
_logger.w("⚠️ Expense update received without ExpenseId: $data");
return;
}
// Update Expense List
_safeControllerUpdate<ExpenseController>(
onFound: (controller) async {
await controller.fetchExpenses();
},
notFoundMessage: '⚠️ ExpenseController not found, cannot refresh list.',
successMessage:
'✅ ExpenseController refreshed from expense notification.',
);
// Update Expense Detail (if open and matches this expenseId)
_safeControllerUpdate<ExpenseDetailController>(
onFound: (controller) async {
// only refresh if the open screen is for this expense
if (controller.expense.value?.id == expenseId) {
await controller.fetchExpenseDetails();
_logger
.i("✅ ExpenseDetailController refreshed for Expense $expenseId");
}
},
notFoundMessage: ' ExpenseDetailController not active, skipping.',
successMessage: '✅ ExpenseDetailController checked for refresh.',
);
}
static void _handleAttendanceUpdated(Map<String, dynamic> data) {
_safeControllerUpdate<AttendanceController>(
onFound: (controller) => controller.refreshDataFromNotification(
projectId: data['ProjectId'],
),
notFoundMessage: '⚠️ AttendanceController not found, cannot update.',
successMessage: '✅ AttendanceController refreshed from notification.',
);
}
static void _handleTaskUpdated(Map<String, dynamic> data,
{required bool isComment}) {
_safeControllerUpdate<DailyTaskController>(
onFound: (controller) => controller.refreshTasksFromNotification(
projectId: data['ProjectId'],
taskAllocationId: data['TaskAllocationId'],
),
notFoundMessage: '⚠️ DailyTaskController not found, cannot update.',
successMessage: '✅ DailyTaskController refreshed from notification.',
);
}
/// Generic reusable method for safe GetX controller access + log handling
static void _safeControllerUpdate<T>({
required void Function(T controller) onFound,
required String notFoundMessage,
required String successMessage,
}) {
try {
final controller = Get.find<T>();
onFound(controller);
_logger.i(successMessage);
} catch (e) {
_logger.w(notFoundMessage);
}
}
}