From ca81da026d32063b30e96a858fb4eae92ea6cf4d Mon Sep 17 00:00:00 2001 From: llsajjad Date: Sat, 27 Sep 2025 14:57:42 +0330 Subject: [PATCH 1/2] Fixed important in notification --- .../repositories/notification_repository.dart | 11 +++++++++++ lib/data/services/api/notification_api.dart | 16 +++++++++------- lib/data/services/notification_service.dart | 17 +++++++++++++---- lib/view_models/notification_view_model.dart | 3 ++- .../widgets/notification_important_tab.dart | 10 +--------- 5 files changed, 36 insertions(+), 21 deletions(-) diff --git a/lib/data/repositories/notification_repository.dart b/lib/data/repositories/notification_repository.dart index fc0075c..4a0db4f 100644 --- a/lib/data/repositories/notification_repository.dart +++ b/lib/data/repositories/notification_repository.dart @@ -1,3 +1,4 @@ +// notification_repository.dart import 'package:tm_app/core/utils/result.dart'; import 'package:tm_app/data/services/model/notification__response/notification_response_model.dart'; import 'package:tm_app/data/services/notification_service.dart'; @@ -28,4 +29,14 @@ class NotificationsRepository { offset: offset, ); } + + Future> getImportantNotifications({ + required int limit, + required int offset, + }) { + return _notificationsService.getImportantNotifications( + limit: limit, + offset: offset, + ); + } } diff --git a/lib/data/services/api/notification_api.dart b/lib/data/services/api/notification_api.dart index a2d0af3..07c4d57 100644 --- a/lib/data/services/api/notification_api.dart +++ b/lib/data/services/api/notification_api.dart @@ -1,17 +1,19 @@ +// notification_api.dart class NotificationApi { static const String notifications = '/api/v1/notifications'; static String getNotifications({required int limit, required int offset}) { return '$notifications?limit=$limit&offset=$offset'; } - static const String feedback = '/api/v1/feedback'; - - static const String markAllAsRead = '/api/v1/notifications/mark'; static const String markAsRead = '/api/v1/notifications/mark-as-read'; - static const String tenderApprovalsTender = '/api/v1/notifications'; + static const String unreadNotifications = '/api/v1/notifications?seen=false'; - static String getUnreadNotifications({required int limit, required int offset}) { - return '$unreadNotifications?limit=$limit&offset=$offset'; + static String getUnreadNotifications({required int limit, required int offset}) { + return '/api/v1/notifications?seen=false&limit=$limit&offset=$offset'; } -} + + static String getImportantNotifications({required int limit, required int offset}) { + return '/api/v1/notifications?priority=important&limit=$limit&offset=$offset'; + } +} \ No newline at end of file diff --git a/lib/data/services/notification_service.dart b/lib/data/services/notification_service.dart index 45e0b25..14eab95 100644 --- a/lib/data/services/notification_service.dart +++ b/lib/data/services/notification_service.dart @@ -1,10 +1,8 @@ // notification_service.dart import 'dart:convert'; - import 'package:tm_app/core/utils/result.dart'; import 'package:tm_app/data/services/api/notification_api.dart'; import 'package:tm_app/data/services/model/notification__response/notification_response_model.dart'; - import '../../core/network/network_manager.dart'; class NotificationsService { @@ -18,7 +16,6 @@ class NotificationsService { }) async { final result = await _networkManager.makeRequest( NotificationApi.getNotifications(limit: limit, offset: offset), - //NotificationApi.notifications, method: 'GET', (json) => NotificationResponseModel.fromJson(json), ); @@ -52,7 +49,19 @@ class NotificationsService { required int offset, }) async { final result = await _networkManager.makeRequest( - NotificationApi.unreadNotifications, + NotificationApi.getUnreadNotifications(limit: limit, offset: offset), + method: 'GET', + (json) => NotificationResponseModel.fromJson(json), + ); + return result; + } + + Future> getImportantNotifications({ + required int limit, + required int offset, + }) async { + final result = await _networkManager.makeRequest( + NotificationApi.getImportantNotifications(limit: limit, offset: offset), method: 'GET', (json) => NotificationResponseModel.fromJson(json), ); diff --git a/lib/view_models/notification_view_model.dart b/lib/view_models/notification_view_model.dart index 43bdf17..db48bbb 100644 --- a/lib/view_models/notification_view_model.dart +++ b/lib/view_models/notification_view_model.dart @@ -1,3 +1,4 @@ +// notification_view_model.dart import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:tm_app/core/utils/app_toast.dart'; @@ -169,7 +170,7 @@ class NotificationViewModel with ChangeNotifier { final int offset = (page - 1) * _pageSize; - final result = await _repository.getUnreadNotifications( + final result = await _repository.getImportantNotifications( limit: _pageSize, offset: offset, ); diff --git a/lib/views/notification/widgets/notification_important_tab.dart b/lib/views/notification/widgets/notification_important_tab.dart index cc00dbe..9d5e417 100644 --- a/lib/views/notification/widgets/notification_important_tab.dart +++ b/lib/views/notification/widgets/notification_important_tab.dart @@ -17,15 +17,7 @@ class NotificationImportantTab extends StatelessWidget { return const Center(child: CircularProgressIndicator()); } - final importantFromApi = viewModel.importantNotificationResponse?.data ?? []; - - final allNotifications = viewModel.allNotificationResponse?.data ?? []; - - final source = importantFromApi.isNotEmpty ? importantFromApi : allNotifications; - - final importantNotifications = source - .where((n) => (n.priority ?? '').toLowerCase() == 'important') - .toList(); + final importantNotifications = viewModel.importantNotificationResponse?.data ?? []; if (importantNotifications.isEmpty) { return const Center(child: Text(NotificationStrings.noImportantNotifications)); From 1fdbff77a1b7857861af63725fdb0d552d75586c Mon Sep 17 00:00:00 2001 From: llsajjad Date: Sat, 27 Sep 2025 15:27:45 +0330 Subject: [PATCH 2/2] fixed pagination --- lib/view_models/notification_view_model.dart | 16 ++++-- .../pages/m_notification_page.dart | 56 ++++++------------- .../strings/notification_strings.dart | 1 + .../widgets/notification_all_tab.dart | 15 ++++- .../widgets/notification_important_tab.dart | 14 +++-- .../widgets/notification_unread_tab.dart | 12 ++-- 6 files changed, 57 insertions(+), 57 deletions(-) diff --git a/lib/view_models/notification_view_model.dart b/lib/view_models/notification_view_model.dart index db48bbb..5be00ca 100644 --- a/lib/view_models/notification_view_model.dart +++ b/lib/view_models/notification_view_model.dart @@ -80,7 +80,8 @@ class NotificationViewModel with ChangeNotifier { } notifyListeners(); - final int offset = (page - 1) * _pageSize; + final int offset = page * _pageSize; + final result = await _repository.getNotifications( limit: _pageSize, offset: offset, @@ -89,10 +90,15 @@ class NotificationViewModel with ChangeNotifier { switch (result) { case Ok(): final data = result.value; + if (isPagination && allNotificationResponse != null) { final old = allNotificationResponse?.data ?? []; final fresh = data.data ?? []; - allNotificationResponse = data.copyWith(data: [...old, ...fresh]); + + allNotificationResponse = allNotificationResponse!.copyWith( + data: [...old, ...fresh], + meta: data.meta, + ); } else { allNotificationResponse = data; } @@ -101,7 +107,7 @@ class NotificationViewModel with ChangeNotifier { currentPageAll = page; totalPagesAll = data.meta?.pages ?? 1; - hasMoreAll = (data.data?.length ?? 0) >= _pageSize; + hasMoreAll = currentPageAll < totalPagesAll; break; case Error(): @@ -125,7 +131,7 @@ class NotificationViewModel with ChangeNotifier { } notifyListeners(); - final int offset = (page - 1) * _pageSize; + final int offset = page * _pageSize; final result = await _repository.getUnreadNotifications( limit: _pageSize, offset: offset, @@ -168,7 +174,7 @@ class NotificationViewModel with ChangeNotifier { } notifyListeners(); - final int offset = (page - 1) * _pageSize; + final int offset = page * _pageSize; final result = await _repository.getImportantNotifications( limit: _pageSize, diff --git a/lib/views/notification/pages/m_notification_page.dart b/lib/views/notification/pages/m_notification_page.dart index 9e91d32..dd94b67 100644 --- a/lib/views/notification/pages/m_notification_page.dart +++ b/lib/views/notification/pages/m_notification_page.dart @@ -24,6 +24,7 @@ class _MobileNotificationPageState extends State final ScrollController _scrollAll = ScrollController(); final ScrollController _scrollUnread = ScrollController(); + final ScrollController _scrollImportant = ScrollController(); @override void initState() { @@ -55,6 +56,18 @@ class _MobileNotificationPageState extends State ); } }); + + _scrollImportant.addListener(() { + if (_scrollImportant.position.pixels >= + _scrollImportant.position.maxScrollExtent - 100 && + !viewModel.isLoadingImportant && + viewModel.hasMoreImportant) { + viewModel.getImportantNotifications( + page: viewModel.currentPageImportant + 1, + isPagination: true, + ); + } + }); } @override @@ -62,6 +75,7 @@ class _MobileNotificationPageState extends State controller.dispose(); _scrollAll.dispose(); _scrollUnread.dispose(); + _scrollImportant.dispose(); super.dispose(); } @@ -83,45 +97,13 @@ class _MobileNotificationPageState extends State ], ), SizedBox(height: 12.0.h()), - Padding( - padding: EdgeInsetsDirectional.only(end: 24.0.w()), - child: Align( - alignment: Alignment.centerRight, - child: InkWell( - onTap: () { - viewModel.markAllAsRead(context); - }, - borderRadius: BorderRadius.circular(99), - child: Container( - width: 132.0.w(), - height: 32.0.h(), - decoration: BoxDecoration( - color: AppColors.primary20, - borderRadius: BorderRadius.circular(99), - ), - child: Center( - child: Text( - NotificationStrings.markAllAsReadButton, - style: TextStyle( - fontSize: 14.0.sp(), - fontWeight: FontWeight.w500, - color: AppColors.mainBlue, - ), - ), - ), - ), - ), - ), - ), - SizedBox(height: 12.0.h()), - Expanded( child: TabBarView( controller: controller, children: [ NotificationAllTab(scrollController: _scrollAll), NotificationUnreadTab(scrollController: _scrollUnread), - const NotificationImportantTab(), + NotificationImportantTab(scrollController: _scrollImportant), ], ), ), @@ -142,11 +124,9 @@ class _MobileNotificationPageState extends State ), ), - if ((viewModel.isLoadingAll && - (viewModel.allNotificationResponse?.data?.isEmpty ?? true)) || - (viewModel.isLoadingUnread && - (viewModel.unreadNotificationResponse?.data?.isEmpty ?? true))) - const Expanded( + if (viewModel.isMoreLoadingImportant) + const Padding( + padding: EdgeInsets.symmetric(vertical: 16), child: Center( child: CircularProgressIndicator(color: AppColors.secondary50), ), diff --git a/lib/views/notification/strings/notification_strings.dart b/lib/views/notification/strings/notification_strings.dart index 32af793..2497f52 100644 --- a/lib/views/notification/strings/notification_strings.dart +++ b/lib/views/notification/strings/notification_strings.dart @@ -24,4 +24,5 @@ class NotificationStrings { static const String noUnreadNotifications = 'No unread notifications'; static const String noImportantNotifications = 'No important notifications'; static const String moreTextButton = 'More'; + static const String noNotifications = 'No notifications'; } diff --git a/lib/views/notification/widgets/notification_all_tab.dart b/lib/views/notification/widgets/notification_all_tab.dart index 6df4c93..d148ddd 100644 --- a/lib/views/notification/widgets/notification_all_tab.dart +++ b/lib/views/notification/widgets/notification_all_tab.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:tm_app/view_models/notification_view_model.dart'; +import 'package:tm_app/views/notification/strings/notification_strings.dart'; import 'notification_card.dart'; @@ -12,8 +13,17 @@ class NotificationAllTab extends StatelessWidget { @override Widget build(BuildContext context) { final viewModel = context.watch(); - final notifications = - viewModel.allNotificationResponse?.data ?? []; + + if (viewModel.isLoadingAll && + (viewModel.allNotificationResponse?.data?.isEmpty ?? true)) { + return const Center(child: CircularProgressIndicator()); + } + + final notifications = viewModel.allNotificationResponse?.data ?? []; + + if (notifications.isEmpty) { + return const Center(child: Text(NotificationStrings.noNotifications)); + } return ListView.builder( controller: scrollController, @@ -28,3 +38,4 @@ class NotificationAllTab extends StatelessWidget { ); } } + diff --git a/lib/views/notification/widgets/notification_important_tab.dart b/lib/views/notification/widgets/notification_important_tab.dart index 9d5e417..93a7f01 100644 --- a/lib/views/notification/widgets/notification_important_tab.dart +++ b/lib/views/notification/widgets/notification_important_tab.dart @@ -13,14 +13,18 @@ class NotificationImportantTab extends StatelessWidget { Widget build(BuildContext context) { final viewModel = context.watch(); - if (viewModel.isLoadingImportant) { + if (viewModel.isLoadingImportant && + (viewModel.importantNotificationResponse?.data?.isEmpty ?? true)) { return const Center(child: CircularProgressIndicator()); } - final importantNotifications = viewModel.importantNotificationResponse?.data ?? []; + final importantNotifications = + viewModel.importantNotificationResponse?.data ?? []; if (importantNotifications.isEmpty) { - return const Center(child: Text(NotificationStrings.noImportantNotifications)); + return const Center( + child: Text(NotificationStrings.noImportantNotifications), + ); } return ListView.builder( @@ -30,9 +34,7 @@ class NotificationImportantTab extends StatelessWidget { final notification = importantNotifications[index]; return Padding( padding: const EdgeInsets.only(bottom: 16.0), - child: NotificationCard( - notification: notification, - ), + child: NotificationCard(notification: notification), ); }, ); diff --git a/lib/views/notification/widgets/notification_unread_tab.dart b/lib/views/notification/widgets/notification_unread_tab.dart index af714ce..a2990a7 100644 --- a/lib/views/notification/widgets/notification_unread_tab.dart +++ b/lib/views/notification/widgets/notification_unread_tab.dart @@ -3,7 +3,6 @@ import 'package:provider/provider.dart'; import 'package:tm_app/core/utils/size_config.dart'; import 'package:tm_app/view_models/notification_view_model.dart'; import 'package:tm_app/views/notification/strings/notification_strings.dart'; - import 'notification_card.dart'; class NotificationUnreadTab extends StatelessWidget { @@ -13,16 +12,17 @@ class NotificationUnreadTab extends StatelessWidget { @override Widget build(BuildContext context) { final viewModel = context.watch(); - - if (viewModel.isLoadingUnread){ + if (viewModel.isLoadingUnread && + (viewModel.unreadNotificationResponse?.data?.isEmpty ?? true)) { return const Center(child: CircularProgressIndicator()); } - final notifications = - viewModel.unreadNotificationResponse?.data ?? []; + final notifications = viewModel.unreadNotificationResponse?.data ?? []; if (notifications.isEmpty) { - return const Center(child: Text(NotificationStrings.noUnreadNotifications,)); + return const Center( + child: Text(NotificationStrings.noUnreadNotifications), + ); } return ListView.builder(