Merge pull request 'update notification tab data when clicking on navigation bars' (#169) from navigate_notification_update into main

Reviewed-on: https://repo.ravanertebat.com/TM/tm_app/pulls/169
This commit is contained in:
a.ghabeli
2025-09-27 10:47:52 +03:30
6 changed files with 139 additions and 90 deletions
@@ -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/view_models/tenders_view_model.dart';
import 'package:tm_app/views/shared/responsive_builder.dart'; import 'package:tm_app/views/shared/responsive_builder.dart';
import '../../../view_models/notification_view_model.dart';
class AppShellScreen extends StatelessWidget { class AppShellScreen extends StatelessWidget {
const AppShellScreen({required this.navigationShell, super.key}); const AppShellScreen({required this.navigationShell, super.key});
@@ -32,6 +34,9 @@ class AppShellScreen extends StatelessWidget {
if (index == 1) { if (index == 1) {
context.read<TendersViewModel>().init(context); context.read<TendersViewModel>().init(context);
} }
if (index == 3) {
context.read<NotificationViewModel>().init();
}
}); });
} }
+68 -28
View File
@@ -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/data/services/model/notification__response/notification_response_model.dart';
import 'package:tm_app/views/notification/strings/notification_strings.dart'; import 'package:tm_app/views/notification/strings/notification_strings.dart';
class NotificationViewModel with ChangeNotifier { class NotificationViewModel with ChangeNotifier {
final NotificationsRepository _repository; final NotificationsRepository _repository;
NotificationViewModel({required NotificationsRepository repositoryViewModel}) NotificationViewModel({required NotificationsRepository repositoryViewModel})
: _repository = repositoryViewModel { : _repository = repositoryViewModel {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
getNotifications(); init();
getUnreadNotifications();
getImportantNotifications();
}); });
} }
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; static const int _pageSize = 10;
String? _errorMessage; String? _errorMessage;
@@ -47,8 +66,10 @@ class NotificationViewModel with ChangeNotifier {
int currentPageImportant = 1; int currentPageImportant = 1;
int totalPagesImportant = 0; int totalPagesImportant = 0;
Future<void> getNotifications({
Future<void> getNotifications({int page = 1, bool isPagination = false}) async { int page = 1,
bool isPagination = false,
}) async {
if (isPagination) { if (isPagination) {
isMoreLoadingAll = true; isMoreLoadingAll = true;
} else { } else {
@@ -57,7 +78,10 @@ class NotificationViewModel with ChangeNotifier {
notifyListeners(); notifyListeners();
final int offset = (page - 1) * _pageSize; 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) { switch (result) {
case Ok<NotificationResponseModel>(): case Ok<NotificationResponseModel>():
@@ -66,9 +90,7 @@ class NotificationViewModel with ChangeNotifier {
final old = allNotificationResponse?.data?.notifications ?? []; final old = allNotificationResponse?.data?.notifications ?? [];
final fresh = data.data?.notifications ?? []; final fresh = data.data?.notifications ?? [];
allNotificationResponse = data.copyWith( allNotificationResponse = data.copyWith(
data: data.data?.copyWith( data: data.data?.copyWith(notifications: [...old, ...fresh]),
notifications: [...old, ...fresh],
),
); );
} else { } else {
allNotificationResponse = data; allNotificationResponse = data;
@@ -91,7 +113,10 @@ class NotificationViewModel with ChangeNotifier {
notifyListeners(); notifyListeners();
} }
Future<void> getUnreadNotifications({int page = 1, bool isPagination = false}) async { Future<void> getUnreadNotifications({
int page = 1,
bool isPagination = false,
}) async {
if (isPagination) { if (isPagination) {
isMoreLoadingUnread = true; isMoreLoadingUnread = true;
} else { } else {
@@ -100,7 +125,10 @@ class NotificationViewModel with ChangeNotifier {
notifyListeners(); notifyListeners();
final int offset = (page - 1) * _pageSize; 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) { switch (result) {
case Ok<NotificationResponseModel>(): case Ok<NotificationResponseModel>():
@@ -109,9 +137,7 @@ class NotificationViewModel with ChangeNotifier {
final old = unreadNotificationResponse?.data?.notifications ?? []; final old = unreadNotificationResponse?.data?.notifications ?? [];
final fresh = data.data?.notifications ?? []; final fresh = data.data?.notifications ?? [];
unreadNotificationResponse = data.copyWith( unreadNotificationResponse = data.copyWith(
data: data.data?.copyWith( data: data.data?.copyWith(notifications: [...old, ...fresh]),
notifications: [...old, ...fresh],
),
); );
} else { } else {
unreadNotificationResponse = data; unreadNotificationResponse = data;
@@ -132,7 +158,10 @@ class NotificationViewModel with ChangeNotifier {
notifyListeners(); notifyListeners();
} }
Future<void> getImportantNotifications({int page = 1, bool isPagination = false}) async { Future<void> getImportantNotifications({
int page = 1,
bool isPagination = false,
}) async {
if (isPagination) { if (isPagination) {
isMoreLoadingImportant = true; isMoreLoadingImportant = true;
} else { } else {
@@ -142,7 +171,10 @@ class NotificationViewModel with ChangeNotifier {
final int offset = (page - 1) * _pageSize; 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) { switch (result) {
case Ok<NotificationResponseModel>(): case Ok<NotificationResponseModel>():
@@ -151,9 +183,7 @@ class NotificationViewModel with ChangeNotifier {
final old = importantNotificationResponse?.data?.notifications ?? []; final old = importantNotificationResponse?.data?.notifications ?? [];
final fresh = data.data?.notifications ?? []; final fresh = data.data?.notifications ?? [];
importantNotificationResponse = data.copyWith( importantNotificationResponse = data.copyWith(
data: data.data?.copyWith( data: data.data?.copyWith(notifications: [...old, ...fresh]),
notifications: [...old, ...fresh],
),
); );
} else { } else {
importantNotificationResponse = data; importantNotificationResponse = data;
@@ -165,7 +195,6 @@ class NotificationViewModel with ChangeNotifier {
break; break;
case Error<NotificationResponseModel>(): case Error<NotificationResponseModel>():
_errorMessage = result.error.toString(); _errorMessage = result.error.toString();
_updateImportantFromAll(); _updateImportantFromAll();
@@ -179,7 +208,8 @@ class NotificationViewModel with ChangeNotifier {
void _updateImportantFromAll() { void _updateImportantFromAll() {
final all = allNotificationResponse?.data?.notifications ?? []; final all = allNotificationResponse?.data?.notifications ?? [];
final filtered = (all.where((n) { final filtered =
(all.where((n) {
final p = n.priority ?? ''; final p = n.priority ?? '';
return p.toLowerCase() == 'important'; return p.toLowerCase() == 'important';
}).toList()); }).toList());
@@ -229,11 +259,14 @@ class NotificationViewModel with ChangeNotifier {
case Ok<Map<String, dynamic>>(): case Ok<Map<String, dynamic>>():
final response = result.value; final response = result.value;
final success = response['success'] as bool? ?? false; 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 (success) {
if (allNotificationResponse?.data?.notifications != null) { if (allNotificationResponse?.data?.notifications != null) {
final updatedNotifications = allNotificationResponse!.data!.notifications! final updatedNotifications =
allNotificationResponse!.data!.notifications!
.map((n) => n.copyWith(seen: true)) .map((n) => n.copyWith(seen: true))
.toList(); .toList();
@@ -244,15 +277,19 @@ class NotificationViewModel with ChangeNotifier {
); );
unreadNotificationResponse = unreadNotificationResponse?.copyWith( unreadNotificationResponse = unreadNotificationResponse?.copyWith(
data: unreadNotificationResponse?.data?.copyWith(notifications: []), data: unreadNotificationResponse?.data?.copyWith(
notifications: [],
),
); );
if (importantNotificationResponse?.data?.notifications != null) { if (importantNotificationResponse?.data?.notifications != null) {
final updatedImportant = importantNotificationResponse!.data!.notifications! final updatedImportant =
importantNotificationResponse!.data!.notifications!
.map((n) => n.copyWith(seen: true)) .map((n) => n.copyWith(seen: true))
.toList(); .toList();
importantNotificationResponse = importantNotificationResponse!.copyWith( importantNotificationResponse = importantNotificationResponse!
.copyWith(
data: importantNotificationResponse!.data!.copyWith( data: importantNotificationResponse!.data!.copyWith(
notifications: updatedImportant, notifications: updatedImportant,
), ),
@@ -261,7 +298,10 @@ class NotificationViewModel with ChangeNotifier {
} }
if (context.mounted) { if (context.mounted) {
AppToast.success(context, NotificationStrings.allNotificationMarkedAsRead); AppToast.success(
context,
NotificationStrings.allNotificationMarkedAsRead,
);
} }
} else { } else {
_errorMessage = message; _errorMessage = message;
+2
View File
@@ -126,6 +126,8 @@ class TendersViewModel with ChangeNotifier {
} }
void init(BuildContext context) async { void init(BuildContext context) async {
_isLoading = true;
notifyListeners();
clearAll(); clearAll();
await getTenders(context: context); await getTenders(context: context);
} }
@@ -53,7 +53,7 @@ class NotificationCard extends StatelessWidget {
Visibility( Visibility(
visible: visible:
notification.priority == notification.priority ==
NotificationStrings.important, NotificationStrings.important.toLowerCase(),
child: Container( child: Container(
width: 86.0.w(), width: 86.0.w(),
height: 24.0.h(), height: 24.0.h(),
@@ -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 'package:tm_app/views/tenders/strings/tenders_strings.dart';
import '../../core/routes/app_routes.dart'; import '../../core/routes/app_routes.dart';
import '../../view_models/notification_view_model.dart';
class DesktopNavigationWidget extends StatelessWidget { class DesktopNavigationWidget extends StatelessWidget {
const DesktopNavigationWidget({ const DesktopNavigationWidget({
@@ -103,7 +104,7 @@ class DesktopNavigationWidget extends StatelessWidget {
context, context,
() => const NotificationRouteData().go(context), () => const NotificationRouteData().go(context),
); );
//context.read<notificationViewModel>().getTenders(); context.read<NotificationViewModel>().init();
} }
}, },
iconPath: AssetsManager.notify, iconPath: AssetsManager.notify,
@@ -148,14 +149,14 @@ class DesktopNavigationWidget extends StatelessWidget {
); );
} }
Widget _navigationItem({ Widget _navigationItem({
required BuildContext context, required BuildContext context,
required String text, required String text,
required bool isActive, required bool isActive,
required VoidCallback onTap, required VoidCallback onTap,
required String iconPath, required String iconPath,
required String activeIconPath, required String activeIconPath,
}) { }) {
final hasUnread = context.watch<HomeViewModel>().hasUnreadNotification; final hasUnread = context.watch<HomeViewModel>().hasUnreadNotification;
return InkWell( return InkWell(
@@ -199,6 +200,5 @@ Widget _navigationItem({
), ),
), ),
); );
} }
} }
@@ -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 'package:tm_app/views/tenders/strings/tenders_strings.dart';
import '../../core/routes/app_routes.dart'; import '../../core/routes/app_routes.dart';
import '../../view_models/notification_view_model.dart';
class TabletNavigationWidget extends StatelessWidget { class TabletNavigationWidget extends StatelessWidget {
const TabletNavigationWidget({required this.currentIndex, super.key}); const TabletNavigationWidget({required this.currentIndex, super.key});
@@ -93,6 +94,7 @@ class TabletNavigationWidget extends StatelessWidget {
context, context,
() => const NotificationRouteData().go(context), () => const NotificationRouteData().go(context),
); );
context.read<NotificationViewModel>().init();
} }
}, },
iconPath: AssetsManager.notify, iconPath: AssetsManager.notify,