From c78c14e4097b6f9636f62ade430cf2476f9a02a4 Mon Sep 17 00:00:00 2001 From: Vaibhav Surve Date: Mon, 3 Nov 2025 16:43:51 +0530 Subject: [PATCH] refactor: Clean up attendance controller initialization and enhance project change handling --- .../attendance_screen_controller.dart | 5 -- lib/helpers/services/api_endpoints.dart | 4 +- .../services/notification_action_handler.dart | 64 ++++++++++++++----- lib/view/Attendence/attendance_screen.dart | 15 ++++- 4 files changed, 63 insertions(+), 25 deletions(-) diff --git a/lib/controller/attendance/attendance_screen_controller.dart b/lib/controller/attendance/attendance_screen_controller.dart index 8e45d48..20ef3d6 100644 --- a/lib/controller/attendance/attendance_screen_controller.dart +++ b/lib/controller/attendance/attendance_screen_controller.dart @@ -51,11 +51,6 @@ class AttendanceController extends GetxController { super.onInit(); _initializeDefaults(); - // 🔹 Fetch organizations for the selected project - final projectId = Get.find().selectedProject?.id; - if (projectId != null) { - fetchOrganizations(projectId); - } } void _initializeDefaults() { diff --git a/lib/helpers/services/api_endpoints.dart b/lib/helpers/services/api_endpoints.dart index 906e33e..d4ad614 100644 --- a/lib/helpers/services/api_endpoints.dart +++ b/lib/helpers/services/api_endpoints.dart @@ -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 diff --git a/lib/helpers/services/notification_action_handler.dart b/lib/helpers/services/notification_action_handler.dart index d21cb32..e799668 100644 --- a/lib/helpers/services/notification_action_handler.dart +++ b/lib/helpers/services/notification_action_handler.dart @@ -69,7 +69,6 @@ class NotificationActionHandler { } break; case 'Team_Modified': - // Call method to handle team modifications and dashboard update _handleDashboardUpdate(data); break; @@ -129,6 +128,11 @@ class NotificationActionHandler { /// ---------------------- HANDLERS ---------------------- static void _handleTaskPlanningUpdated(Map data) { + if (!_isCurrentProject(data)) { + _logger.i("â„šī¸ Ignored task planning update from another project."); + return; + } + final projectId = data['ProjectId']; if (projectId == null) { _logger.w("âš ī¸ TaskPlanning update received without ProjectId: $data"); @@ -159,13 +163,17 @@ class NotificationActionHandler { } static void _handleExpenseUpdated(Map data) { + if (!_isCurrentProject(data)) { + _logger.i("â„šī¸ Ignored expense update from another project."); + return; + } + final expenseId = data['ExpenseId']; if (expenseId == null) { _logger.w("âš ī¸ Expense update received without ExpenseId: $data"); return; } - // Update Expense List _safeControllerUpdate( onFound: (controller) async { await controller.fetchExpenses(); @@ -175,7 +183,6 @@ class NotificationActionHandler { '✅ ExpenseController refreshed from expense notification.', ); - // Update Expense Detail (if open and matches this expenseId) _safeControllerUpdate( onFound: (controller) async { if (controller.expense.value?.id == expenseId) { @@ -190,6 +197,11 @@ class NotificationActionHandler { } static void _handleAttendanceUpdated(Map data) { + if (!_isCurrentProject(data)) { + _logger.i("â„šī¸ Ignored attendance update from another project."); + return; + } + _safeControllerUpdate( onFound: (controller) => controller.refreshDataFromNotification( projectId: data['ProjectId'], @@ -201,6 +213,11 @@ class NotificationActionHandler { static void _handleTaskUpdated(Map data, {required bool isComment}) { + if (!_isCurrentProject(data)) { + _logger.i("â„šī¸ Ignored task update from another project."); + return; + } + _safeControllerUpdate( onFound: (controller) => controller.refreshTasksFromNotification( projectId: data['ProjectId'], @@ -213,11 +230,15 @@ class NotificationActionHandler { /// ---------------------- DOCUMENT HANDLER ---------------------- static void _handleDocumentModified(Map data) { + if (!_isCurrentProject(data)) { + _logger.i("â„šī¸ Ignored document update from another project."); + return; + } + String entityTypeId; String entityId; String? documentId = data['DocumentId']; - // Determine entity type and ID if (data['Keyword'] == 'Employee_Document_Modified') { entityTypeId = Permissions.employeeEntity; entityId = data['EmployeeId'] ?? ''; @@ -237,7 +258,6 @@ class NotificationActionHandler { _logger.i( "🔔 Document notification received: keyword=${data['Keyword']}, entityTypeId=$entityTypeId, entityId=$entityId, documentId=$documentId"); - // Refresh Document List if (Get.isRegistered()) { _safeControllerUpdate( onFound: (controller) async { @@ -255,11 +275,9 @@ class NotificationActionHandler { _logger.w('âš ī¸ DocumentController not registered, skipping list refresh.'); } - // Refresh Document Details (if open) if (documentId != null && Get.isRegistered()) { _safeControllerUpdate( onFound: (controller) async { - // Refresh details regardless of current document await controller.fetchDocumentDetails(documentId); _logger.i( "✅ DocumentDetailsController refreshed for Document $documentId"); @@ -276,13 +294,10 @@ class NotificationActionHandler { /// ---------------------- DIRECTORY HANDLERS ---------------------- static void _handleContactModified(Map data) { - final contactId = data['ContactId']; - - // Always refresh the contact list _safeControllerUpdate( onFound: (controller) { controller.fetchContacts(); - // If a specific contact is provided, refresh its notes as well + final contactId = data['ContactId']; if (contactId != null) { controller.fetchCommentsForContact(contactId); } @@ -293,7 +308,6 @@ class NotificationActionHandler { '✅ Directory contacts (and notes if applicable) refreshed from notification.', ); - // Refresh notes globally as well _safeControllerUpdate( onFound: (controller) => controller.fetchNotes(), notFoundMessage: 'âš ī¸ NotesController not found, cannot refresh notes.', @@ -302,7 +316,6 @@ class NotificationActionHandler { } static void _handleContactNoteModified(Map data) { - // Refresh both contacts and notes when a note is modified _handleContactModified(data); } @@ -324,6 +337,11 @@ class NotificationActionHandler { /// ---------------------- DASHBOARD HANDLER ---------------------- static void _handleDashboardUpdate(Map data) { + if (!_isCurrentProject(data)) { + _logger.i("â„šī¸ Ignored dashboard update from another project."); + return; + } + _safeControllerUpdate( onFound: (controller) async { final type = data['type'] ?? ''; @@ -347,11 +365,9 @@ class NotificationActionHandler { controller.projectController.selectedProjectId.value; final projectIdsString = data['ProjectIds'] ?? ''; - // Convert comma-separated string to List 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); } @@ -375,6 +391,24 @@ class NotificationActionHandler { /// ---------------------- UTILITY ---------------------- + static bool _isCurrentProject(Map data) { + try { + final dashboard = Get.find(); + final currentProjectId = + dashboard.projectController.selectedProjectId.value; + final notificationProjectId = data['ProjectId']?.toString(); + + if (notificationProjectId == null || notificationProjectId.isEmpty) { + return true; // No project info → allow global refresh + } + + return notificationProjectId == currentProjectId; + } catch (e) { + _logger.w("âš ī¸ Could not verify project context: $e"); + return true; + } + } + static void _safeControllerUpdate({ required void Function(T controller) onFound, required String notFoundMessage, diff --git a/lib/view/Attendence/attendance_screen.dart b/lib/view/Attendence/attendance_screen.dart index 32d3d8d..11edab3 100644 --- a/lib/view/Attendence/attendance_screen.dart +++ b/lib/view/Attendence/attendance_screen.dart @@ -34,12 +34,12 @@ class _AttendanceScreenState extends State with UIMixin { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { - // Listen for future project selection changes + // 🔁 Listen for project changes ever(projectController.selectedProjectId, (projectId) async { if (projectId.isNotEmpty) await _loadData(projectId); }); - // Load initial data + // 🚀 Load initial data only once the screen is shown final projectId = projectController.selectedProjectId.value; if (projectId.isNotEmpty) _loadData(projectId); }); @@ -47,7 +47,7 @@ class _AttendanceScreenState extends State with UIMixin { Future _loadData(String projectId) async { try { - attendanceController.selectedTab = 'todaysAttendance'; + attendanceController.selectedTab = 'todaysAttendance'; await attendanceController.loadAttendanceData(projectId); attendanceController.update(['attendance_dashboard_controller']); } catch (e) { @@ -402,4 +402,13 @@ class _AttendanceScreenState extends State with UIMixin { ), ); } + + @override + void dispose() { + // 🧹 Clean up the controller when user leaves this screen + if (Get.isRegistered()) { + Get.delete(); + } + super.dispose(); + } }