Merge pull request 'mark single notification as read' (#186) from seen_notification into main
Reviewed-on: https://repo.ravanertebat.com/TM/tm_app/pulls/186
This commit is contained in:
@@ -159,8 +159,10 @@ List<SingleChildWidget> get viewModels {
|
||||
),
|
||||
ChangeNotifierProvider(
|
||||
create:
|
||||
(context) =>
|
||||
NotificationViewModel(repositoryViewModel: context.read()),
|
||||
(context) => NotificationViewModel(
|
||||
repositoryViewModel: context.read(),
|
||||
homeViewModel: context.read(),
|
||||
),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -39,4 +39,10 @@ class NotificationsRepository {
|
||||
offset: offset,
|
||||
);
|
||||
}
|
||||
|
||||
Future<Result<NotificationResponseModel>> markAsRead({
|
||||
required String notificationId,
|
||||
}) {
|
||||
return _notificationsService.markAsRead(notificationId: notificationId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,14 +6,20 @@ class NotificationApi {
|
||||
}
|
||||
|
||||
static const String markAllAsRead = '/api/v1/notifications/mark';
|
||||
static const String markAsRead = '/api/v1/notifications/mark-as-read';
|
||||
static const String markAsRead = '/api/v1/notifications/mark';
|
||||
|
||||
static const String unreadNotifications = '/api/v1/notifications?seen=false';
|
||||
static String getUnreadNotifications({required int limit, required int 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}) {
|
||||
static String getImportantNotifications({
|
||||
required int limit,
|
||||
required int offset,
|
||||
}) {
|
||||
return '/api/v1/notifications?priority=important&limit=$limit&offset=$offset';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +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 {
|
||||
@@ -34,13 +34,11 @@ class NotificationsService {
|
||||
Future<Result<NotificationResponseModel>> markAsRead({
|
||||
required String notificationId,
|
||||
}) async {
|
||||
final data = jsonEncode({'notification_id': notificationId});
|
||||
final result = await _networkManager.makeRequest(
|
||||
NotificationApi.markAsRead,
|
||||
method: 'POST',
|
||||
'${NotificationApi.markAsRead}/$notificationId',
|
||||
method: 'GET',
|
||||
(json) => NotificationResponseModel.fromJson(json),
|
||||
data: data,
|
||||
);
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// notification_view_model.dart
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tm_app/core/utils/app_toast.dart';
|
||||
import 'package:tm_app/core/utils/result.dart';
|
||||
import 'package:tm_app/data/repositories/notification_repository.dart';
|
||||
@@ -10,9 +9,13 @@ import 'package:tm_app/views/notification/strings/notification_strings.dart';
|
||||
|
||||
class NotificationViewModel with ChangeNotifier {
|
||||
final NotificationsRepository _repository;
|
||||
final HomeViewModel _homeViewModel;
|
||||
|
||||
NotificationViewModel({required NotificationsRepository repositoryViewModel})
|
||||
: _repository = repositoryViewModel {
|
||||
NotificationViewModel({
|
||||
required NotificationsRepository repositoryViewModel,
|
||||
required HomeViewModel homeViewModel,
|
||||
}) : _repository = repositoryViewModel,
|
||||
_homeViewModel = homeViewModel {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
init();
|
||||
});
|
||||
@@ -214,10 +217,10 @@ class NotificationViewModel with ChangeNotifier {
|
||||
void _updateImportantFromAll() {
|
||||
final all = allNotificationResponse?.data ?? [];
|
||||
final filtered =
|
||||
(all.where((n) {
|
||||
all.where((n) {
|
||||
final p = n.priority ?? '';
|
||||
return p.toLowerCase() == 'important';
|
||||
}).toList());
|
||||
}).toList();
|
||||
|
||||
if (allNotificationResponse != null) {
|
||||
importantNotificationResponse = allNotificationResponse!.copyWith(
|
||||
@@ -294,6 +297,9 @@ class NotificationViewModel with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure unread list is empty after marking all as read
|
||||
_checkAndUpdateUnreadState();
|
||||
|
||||
if (context.mounted) {
|
||||
AppToast.success(
|
||||
context,
|
||||
@@ -341,12 +347,100 @@ class NotificationViewModel with ChangeNotifier {
|
||||
}
|
||||
|
||||
void setNotificationFalse(BuildContext context) {
|
||||
final homeViewModel = context.read<HomeViewModel>();
|
||||
homeViewModel.setUnreadNotificationFalse();
|
||||
_homeViewModel.setUnreadNotificationFalse();
|
||||
}
|
||||
|
||||
void checkNotifications(BuildContext context) {
|
||||
final homeViewModel = context.read<HomeViewModel>();
|
||||
homeViewModel.checkUnreadNotifications();
|
||||
void _checkAndUpdateUnreadState() {
|
||||
// Check if all notifications are read
|
||||
final allNotifications = allNotificationResponse?.data ?? [];
|
||||
final hasUnreadNotifications = allNotifications.any((n) => n.seen != true);
|
||||
|
||||
if (!hasUnreadNotifications) {
|
||||
// Clear unread list if all notifications are read
|
||||
unreadNotificationResponse = unreadNotificationResponse?.copyWith(
|
||||
data: [],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
int get unreadCount {
|
||||
return unreadNotificationResponse?.data?.length ?? 0;
|
||||
}
|
||||
|
||||
int get importantCount {
|
||||
return importantNotificationResponse?.data?.length ?? 0;
|
||||
}
|
||||
|
||||
bool get hasUnreadNotifications {
|
||||
return unreadCount > 0;
|
||||
}
|
||||
|
||||
bool get hasImportantNotifications {
|
||||
return importantCount > 0;
|
||||
}
|
||||
|
||||
void checkNotifications() {
|
||||
_homeViewModel.checkUnreadNotifications();
|
||||
}
|
||||
|
||||
Future<void> markAsRead({required String notificationId}) async {
|
||||
final result = await _repository.markAsRead(notificationId: notificationId);
|
||||
|
||||
switch (result) {
|
||||
case Ok<NotificationResponseModel>():
|
||||
// Find and update only the specific notification that matches the ID
|
||||
final updatedNotifications =
|
||||
allNotificationResponse?.data?.map((n) {
|
||||
if (n.id == notificationId) {
|
||||
return n.copyWith(seen: true);
|
||||
}
|
||||
return n;
|
||||
}).toList();
|
||||
|
||||
if (updatedNotifications != null) {
|
||||
allNotificationResponse = allNotificationResponse!.copyWith(
|
||||
data: updatedNotifications,
|
||||
);
|
||||
}
|
||||
|
||||
// Update unread list - remove the notification that was marked as read
|
||||
if (unreadNotificationResponse?.data != null) {
|
||||
final updatedUnreadList =
|
||||
unreadNotificationResponse!.data!
|
||||
.where((n) => n.id != notificationId)
|
||||
.toList();
|
||||
|
||||
unreadNotificationResponse = unreadNotificationResponse!.copyWith(
|
||||
data: updatedUnreadList,
|
||||
);
|
||||
}
|
||||
|
||||
// Update important list - mark the notification as seen if it exists
|
||||
if (importantNotificationResponse?.data != null) {
|
||||
final updatedImportantList =
|
||||
importantNotificationResponse!.data!.map((n) {
|
||||
if (n.id == notificationId) {
|
||||
return n.copyWith(seen: true);
|
||||
}
|
||||
return n;
|
||||
}).toList();
|
||||
|
||||
importantNotificationResponse = importantNotificationResponse!
|
||||
.copyWith(data: updatedImportantList);
|
||||
}
|
||||
|
||||
// Check if all notifications are now read
|
||||
_checkAndUpdateUnreadState();
|
||||
|
||||
notifyListeners();
|
||||
checkNotifications();
|
||||
|
||||
break;
|
||||
case Error<NotificationResponseModel>():
|
||||
_errorMessage = result.error.toString();
|
||||
break;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +123,7 @@ class NotificationCard extends StatelessWidget {
|
||||
const Spacer(),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
viewModel.markAsRead(notificationId: notification.id!);
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
@@ -131,11 +132,7 @@ class NotificationCard extends StatelessWidget {
|
||||
viewModel: viewModel,
|
||||
);
|
||||
},
|
||||
).then((value) {
|
||||
if (context.mounted) {
|
||||
viewModel.checkNotifications(context);
|
||||
}
|
||||
});
|
||||
);
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
|
||||
Reference in New Issue
Block a user