From ae348c3ed90a35ee8c73a5123dbeef14937b3eec Mon Sep 17 00:00:00 2001 From: amirrezaghabeli Date: Sat, 27 Sep 2025 10:47:13 +0330 Subject: [PATCH] update notification tab data when clicking on navigation bars --- .../routes/app_shell/app_shell_screen.dart | 5 + lib/view_models/notification_view_model.dart | 120 ++++++++++++------ lib/view_models/tenders_view_model.dart | 2 + .../widgets/notification_card.dart | 2 +- .../shared/desktop_navigation_widget.dart | 98 +++++++------- .../shared/tablet_navigation_widget.dart | 2 + 6 files changed, 139 insertions(+), 90 deletions(-) diff --git a/lib/core/routes/app_shell/app_shell_screen.dart b/lib/core/routes/app_shell/app_shell_screen.dart index c6c3d35..fbd8d74 100644 --- a/lib/core/routes/app_shell/app_shell_screen.dart +++ b/lib/core/routes/app_shell/app_shell_screen.dart @@ -8,6 +8,8 @@ import 'package:tm_app/view_models/home_view_model.dart'; import 'package:tm_app/view_models/tenders_view_model.dart'; import 'package:tm_app/views/shared/responsive_builder.dart'; +import '../../../view_models/notification_view_model.dart'; + class AppShellScreen extends StatelessWidget { const AppShellScreen({required this.navigationShell, super.key}); @@ -32,6 +34,9 @@ class AppShellScreen extends StatelessWidget { if (index == 1) { context.read().init(context); } + if (index == 3) { + context.read().init(); + } }); } diff --git a/lib/view_models/notification_view_model.dart b/lib/view_models/notification_view_model.dart index ddbfe5e..24e3ac8 100644 --- a/lib/view_models/notification_view_model.dart +++ b/lib/view_models/notification_view_model.dart @@ -5,19 +5,38 @@ import 'package:tm_app/data/repositories/notification_repository.dart'; import 'package:tm_app/data/services/model/notification__response/notification_response_model.dart'; import 'package:tm_app/views/notification/strings/notification_strings.dart'; - class NotificationViewModel with ChangeNotifier { final NotificationsRepository _repository; NotificationViewModel({required NotificationsRepository repositoryViewModel}) - : _repository = repositoryViewModel { + : _repository = repositoryViewModel { WidgetsBinding.instance.addPostFrameCallback((_) { - getNotifications(); - getUnreadNotifications(); - getImportantNotifications(); + init(); }); } + void init() async { + clearData(); + await getNotifications(); + await getUnreadNotifications(); + await getImportantNotifications(); + } + + void clearData() { + allNotificationResponse = null; + unreadNotificationResponse = null; + importantNotificationResponse = null; + _errorMessage = null; + currentPageAll = 1; + totalPagesAll = 0; + currentPageUnread = 1; + totalPagesUnread = 0; + currentPageImportant = 1; + totalPagesImportant = 0; + + notifyListeners(); + } + static const int _pageSize = 10; String? _errorMessage; @@ -47,8 +66,10 @@ class NotificationViewModel with ChangeNotifier { int currentPageImportant = 1; int totalPagesImportant = 0; - - Future getNotifications({int page = 1, bool isPagination = false}) async { + Future getNotifications({ + int page = 1, + bool isPagination = false, + }) async { if (isPagination) { isMoreLoadingAll = true; } else { @@ -57,7 +78,10 @@ class NotificationViewModel with ChangeNotifier { notifyListeners(); final int offset = (page - 1) * _pageSize; - final result = await _repository.getNotifications(limit: _pageSize, offset: offset); + final result = await _repository.getNotifications( + limit: _pageSize, + offset: offset, + ); switch (result) { case Ok(): @@ -66,9 +90,7 @@ class NotificationViewModel with ChangeNotifier { final old = allNotificationResponse?.data?.notifications ?? []; final fresh = data.data?.notifications ?? []; allNotificationResponse = data.copyWith( - data: data.data?.copyWith( - notifications: [...old, ...fresh], - ), + data: data.data?.copyWith(notifications: [...old, ...fresh]), ); } else { allNotificationResponse = data; @@ -91,7 +113,10 @@ class NotificationViewModel with ChangeNotifier { notifyListeners(); } - Future getUnreadNotifications({int page = 1, bool isPagination = false}) async { + Future getUnreadNotifications({ + int page = 1, + bool isPagination = false, + }) async { if (isPagination) { isMoreLoadingUnread = true; } else { @@ -100,7 +125,10 @@ class NotificationViewModel with ChangeNotifier { notifyListeners(); final int offset = (page - 1) * _pageSize; - final result = await _repository.getUnreadNotifications(limit: _pageSize, offset: offset); + final result = await _repository.getUnreadNotifications( + limit: _pageSize, + offset: offset, + ); switch (result) { case Ok(): @@ -109,9 +137,7 @@ class NotificationViewModel with ChangeNotifier { final old = unreadNotificationResponse?.data?.notifications ?? []; final fresh = data.data?.notifications ?? []; unreadNotificationResponse = data.copyWith( - data: data.data?.copyWith( - notifications: [...old, ...fresh], - ), + data: data.data?.copyWith(notifications: [...old, ...fresh]), ); } else { unreadNotificationResponse = data; @@ -132,7 +158,10 @@ class NotificationViewModel with ChangeNotifier { notifyListeners(); } - Future getImportantNotifications({int page = 1, bool isPagination = false}) async { + Future getImportantNotifications({ + int page = 1, + bool isPagination = false, + }) async { if (isPagination) { isMoreLoadingImportant = true; } else { @@ -142,7 +171,10 @@ class NotificationViewModel with ChangeNotifier { final int offset = (page - 1) * _pageSize; - final result = await _repository.getUnreadNotifications(limit: _pageSize, offset: offset); + final result = await _repository.getUnreadNotifications( + limit: _pageSize, + offset: offset, + ); switch (result) { case Ok(): @@ -151,9 +183,7 @@ class NotificationViewModel with ChangeNotifier { final old = importantNotificationResponse?.data?.notifications ?? []; final fresh = data.data?.notifications ?? []; importantNotificationResponse = data.copyWith( - data: data.data?.copyWith( - notifications: [...old, ...fresh], - ), + data: data.data?.copyWith(notifications: [...old, ...fresh]), ); } else { importantNotificationResponse = data; @@ -165,7 +195,6 @@ class NotificationViewModel with ChangeNotifier { break; case Error(): - _errorMessage = result.error.toString(); _updateImportantFromAll(); @@ -179,10 +208,11 @@ class NotificationViewModel with ChangeNotifier { void _updateImportantFromAll() { final all = allNotificationResponse?.data?.notifications ?? []; - final filtered = (all.where((n) { - final p = n.priority ?? ''; - return p.toLowerCase() == 'important'; - }).toList()); + final filtered = + (all.where((n) { + final p = n.priority ?? ''; + return p.toLowerCase() == 'important'; + }).toList()); if (allNotificationResponse != null) { importantNotificationResponse = allNotificationResponse!.copyWith( @@ -229,13 +259,16 @@ class NotificationViewModel with ChangeNotifier { case Ok>(): final response = result.value; final success = response['success'] as bool? ?? false; - final message = response['message'] as String? ?? NotificationStrings.unknownResponse; + final message = + response['message'] as String? ?? + NotificationStrings.unknownResponse; if (success) { if (allNotificationResponse?.data?.notifications != null) { - final updatedNotifications = allNotificationResponse!.data!.notifications! - .map((n) => n.copyWith(seen: true)) - .toList(); + final updatedNotifications = + allNotificationResponse!.data!.notifications! + .map((n) => n.copyWith(seen: true)) + .toList(); allNotificationResponse = allNotificationResponse!.copyWith( data: allNotificationResponse!.data!.copyWith( @@ -244,24 +277,31 @@ class NotificationViewModel with ChangeNotifier { ); unreadNotificationResponse = unreadNotificationResponse?.copyWith( - data: unreadNotificationResponse?.data?.copyWith(notifications: []), + data: unreadNotificationResponse?.data?.copyWith( + notifications: [], + ), ); if (importantNotificationResponse?.data?.notifications != null) { - final updatedImportant = importantNotificationResponse!.data!.notifications! - .map((n) => n.copyWith(seen: true)) - .toList(); + final updatedImportant = + importantNotificationResponse!.data!.notifications! + .map((n) => n.copyWith(seen: true)) + .toList(); - importantNotificationResponse = importantNotificationResponse!.copyWith( - data: importantNotificationResponse!.data!.copyWith( - notifications: updatedImportant, - ), - ); + importantNotificationResponse = importantNotificationResponse! + .copyWith( + data: importantNotificationResponse!.data!.copyWith( + notifications: updatedImportant, + ), + ); } } if (context.mounted) { - AppToast.success(context, NotificationStrings.allNotificationMarkedAsRead); + AppToast.success( + context, + NotificationStrings.allNotificationMarkedAsRead, + ); } } else { _errorMessage = message; diff --git a/lib/view_models/tenders_view_model.dart b/lib/view_models/tenders_view_model.dart index 3bf35d7..c092e88 100644 --- a/lib/view_models/tenders_view_model.dart +++ b/lib/view_models/tenders_view_model.dart @@ -126,6 +126,8 @@ class TendersViewModel with ChangeNotifier { } void init(BuildContext context) async { + _isLoading = true; + notifyListeners(); clearAll(); await getTenders(context: context); } diff --git a/lib/views/notification/widgets/notification_card.dart b/lib/views/notification/widgets/notification_card.dart index d291abe..0d97fdf 100644 --- a/lib/views/notification/widgets/notification_card.dart +++ b/lib/views/notification/widgets/notification_card.dart @@ -53,7 +53,7 @@ class NotificationCard extends StatelessWidget { Visibility( visible: notification.priority == - NotificationStrings.important, + NotificationStrings.important.toLowerCase(), child: Container( width: 86.0.w(), height: 24.0.h(), diff --git a/lib/views/shared/desktop_navigation_widget.dart b/lib/views/shared/desktop_navigation_widget.dart index 9ae485e..75f20f5 100644 --- a/lib/views/shared/desktop_navigation_widget.dart +++ b/lib/views/shared/desktop_navigation_widget.dart @@ -11,6 +11,7 @@ import 'package:tm_app/views/profile/strings/profile_strings.dart'; import 'package:tm_app/views/tenders/strings/tenders_strings.dart'; import '../../core/routes/app_routes.dart'; +import '../../view_models/notification_view_model.dart'; class DesktopNavigationWidget extends StatelessWidget { const DesktopNavigationWidget({ @@ -103,7 +104,7 @@ class DesktopNavigationWidget extends StatelessWidget { context, () => const NotificationRouteData().go(context), ); - //context.read().getTenders(); + context.read().init(); } }, iconPath: AssetsManager.notify, @@ -148,57 +149,56 @@ class DesktopNavigationWidget extends StatelessWidget { ); } -Widget _navigationItem({ - required BuildContext context, - required String text, - required bool isActive, - required VoidCallback onTap, - required String iconPath, - required String activeIconPath, -}) { - final hasUnread = context.watch().hasUnreadNotification; + Widget _navigationItem({ + required BuildContext context, + required String text, + required bool isActive, + required VoidCallback onTap, + required String iconPath, + required String activeIconPath, + }) { + final hasUnread = context.watch().hasUnreadNotification; - return InkWell( - onTap: onTap, - child: SizedBox( - width: 115.0, - height: 64, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Stack( - clipBehavior: Clip.none, - children: [ - SvgPicture.asset(isActive ? activeIconPath : iconPath), - if (text == TendersStrings.notifications && hasUnread) - Positioned( - right: -5, - top: -2, - child: Container( - width: 8, - height: 8, - decoration: const BoxDecoration( - color: Colors.red, - shape: BoxShape.circle, + return InkWell( + onTap: onTap, + child: SizedBox( + width: 115.0, + height: 64, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Stack( + clipBehavior: Clip.none, + children: [ + SvgPicture.asset(isActive ? activeIconPath : iconPath), + if (text == TendersStrings.notifications && hasUnread) + Positioned( + right: -5, + top: -2, + child: Container( + width: 8, + height: 8, + decoration: const BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, + ), ), ), - ), - ], - ), - const SizedBox(width: 8), - Text( - text, - style: TextStyle( - fontSize: 12.0.sp(), - fontWeight: FontWeight.w400, - color: isActive ? AppColors.primaryColor : AppColors.grey60, + ], ), - ), - ], + const SizedBox(width: 8), + Text( + text, + style: TextStyle( + fontSize: 12.0.sp(), + fontWeight: FontWeight.w400, + color: isActive ? AppColors.primaryColor : AppColors.grey60, + ), + ), + ], + ), ), - ), - ); -} - + ); + } } diff --git a/lib/views/shared/tablet_navigation_widget.dart b/lib/views/shared/tablet_navigation_widget.dart index d2043ca..90ad5fc 100644 --- a/lib/views/shared/tablet_navigation_widget.dart +++ b/lib/views/shared/tablet_navigation_widget.dart @@ -12,6 +12,7 @@ import 'package:tm_app/views/profile/strings/profile_strings.dart'; import 'package:tm_app/views/tenders/strings/tenders_strings.dart'; import '../../core/routes/app_routes.dart'; +import '../../view_models/notification_view_model.dart'; class TabletNavigationWidget extends StatelessWidget { const TabletNavigationWidget({required this.currentIndex, super.key}); @@ -93,6 +94,7 @@ class TabletNavigationWidget extends StatelessWidget { context, () => const NotificationRouteData().go(context), ); + context.read().init(); } }, iconPath: AssetsManager.notify,