230 lines
6.7 KiB
Dart
230 lines
6.7 KiB
Dart
import 'dart:developer';
|
|
import 'package:get/get.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:onufitness/constants/api_enum_constant.dart';
|
|
import 'package:onufitness/models/notification/get_all_notification_response_model.dart';
|
|
import 'package:onufitness/services/api_services/base_api_services.dart';
|
|
|
|
class NotificationController extends GetxController {
|
|
// Observables
|
|
var notificationResponse = Rxn<GetAllNotificationResponseModel>();
|
|
var isLoading = true.obs;
|
|
var isLoadingMore = false.obs;
|
|
var errorMessage = RxnString();
|
|
var hasReachedEnd = false.obs;
|
|
|
|
// Pagination variables
|
|
var currentPage = 1.obs;
|
|
static const int pageSize = 20;
|
|
var allNotifications = <NotificationItem>[].obs;
|
|
|
|
// Scroll controller for pagination
|
|
final ScrollController scrollController = ScrollController();
|
|
|
|
@override
|
|
void onInit() {
|
|
super.onInit();
|
|
_setupScrollListener();
|
|
fetchNotifications(isRefresh: true);
|
|
}
|
|
|
|
@override
|
|
void onClose() {
|
|
scrollController.dispose();
|
|
super.onClose();
|
|
}
|
|
|
|
void _setupScrollListener() {
|
|
scrollController.addListener(() {
|
|
if (scrollController.position.pixels >=
|
|
scrollController.position.maxScrollExtent - 200) {
|
|
if (!isLoadingMore.value && !hasReachedEnd.value) {
|
|
loadMore();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Getters
|
|
List<NotificationItem> get notifications => allNotifications;
|
|
int get totalUnseenCount =>
|
|
notificationResponse.value?.data?.totalUnseenCount ?? 0;
|
|
bool get hasUnreadNotifications => totalUnseenCount > 0;
|
|
|
|
//fetch Notifications API Call ................................................................................
|
|
Future<void> fetchNotifications({bool isRefresh = false}) async {
|
|
try {
|
|
if (isRefresh) {
|
|
isLoading.value = true;
|
|
currentPage.value = 1;
|
|
hasReachedEnd.value = false;
|
|
allNotifications.clear();
|
|
}
|
|
|
|
errorMessage.value = null;
|
|
|
|
final response = await ApiBase.getRequest(
|
|
extendedURL:
|
|
"/api/Notifications/get-notifications-by-userID?PageNumber=${currentPage.value}&PageSize=$pageSize",
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
final responseModel = getAllNotificationResponseModelFromJson(
|
|
response.body,
|
|
);
|
|
|
|
notificationResponse.value = responseModel;
|
|
|
|
if (responseModel.data?.items != null) {
|
|
if (isRefresh) {
|
|
allNotifications.value = responseModel.data!.items!;
|
|
} else {
|
|
allNotifications.addAll(responseModel.data!.items!);
|
|
}
|
|
|
|
// Check if we've reached the end
|
|
if (responseModel.data!.items!.length < pageSize) {
|
|
hasReachedEnd.value = true;
|
|
}
|
|
} else {
|
|
hasReachedEnd.value = true;
|
|
}
|
|
} else {
|
|
errorMessage.value = 'Failed to load notifications';
|
|
}
|
|
} catch (e) {
|
|
errorMessage.value = 'Error: $e';
|
|
} finally {
|
|
isLoading.value = false;
|
|
isLoadingMore.value = false;
|
|
}
|
|
}
|
|
|
|
//..............................................................................................................
|
|
//..............................................................................................................
|
|
Future<void> loadMore() async {
|
|
if (hasReachedEnd.value || isLoadingMore.value) return;
|
|
|
|
isLoadingMore.value = true;
|
|
currentPage.value++;
|
|
|
|
await fetchNotifications(isRefresh: false);
|
|
}
|
|
|
|
Future<void> refreshNotifications() async {
|
|
await fetchNotifications(isRefresh: true);
|
|
}
|
|
|
|
Future<void> markNotificationAsRead(int notificationId) async {
|
|
log("Entered in markNotificationAsRead");
|
|
try {
|
|
final response = await ApiBase.patchRequest(
|
|
extendedURL: "/api/Notifications/update-notification/$notificationId",
|
|
);
|
|
log(response.statusCode.toString());
|
|
log(response.body.toString());
|
|
|
|
if (response.statusCode == 200) {
|
|
// Update local state
|
|
final itemIndex = allNotifications.indexWhere(
|
|
(item) => item.notificationId == notificationId,
|
|
);
|
|
|
|
if (itemIndex != -1) {
|
|
allNotifications[itemIndex].isSeen = true;
|
|
// Update unseen count
|
|
if (notificationResponse.value?.data != null) {
|
|
notificationResponse.value!.data!.totalUnseenCount =
|
|
(notificationResponse.value!.data!.totalUnseenCount ?? 1) - 1;
|
|
}
|
|
// Trigger reactive update
|
|
allNotifications.refresh();
|
|
notificationResponse.refresh();
|
|
}
|
|
}
|
|
} catch (e) {
|
|
log("Catch : Failed to Mark Read notification");
|
|
}
|
|
}
|
|
|
|
Future<void> markAllAsRead() async {
|
|
log("markAllAsRead");
|
|
try {
|
|
final response = await ApiBase.patchRequest(
|
|
extendedURL: "/api/Notifications/mark-all-as-read",
|
|
);
|
|
log(response.statusCode.toString());
|
|
log(response.body.toString());
|
|
|
|
if (response.statusCode == 200) {
|
|
// Update local state
|
|
for (var item in allNotifications) {
|
|
item.isSeen = true;
|
|
}
|
|
// Update unseen count
|
|
if (notificationResponse.value?.data != null) {
|
|
notificationResponse.value!.data!.totalUnseenCount = 0;
|
|
}
|
|
allNotifications.refresh();
|
|
notificationResponse.refresh();
|
|
}
|
|
} catch (e) {
|
|
log("Catch : Failed to Mark all Read notification");
|
|
}
|
|
}
|
|
|
|
// Utility Methods
|
|
IconData getNotificationIcon(int? notificationType) {
|
|
switch (notificationType) {
|
|
case ApiEnum.Goal:
|
|
return Icons.fitness_center;
|
|
case ApiEnum.Challenge:
|
|
return Icons.event;
|
|
case ApiEnum.ConnectionRequest:
|
|
return Icons.people;
|
|
case ApiEnum.Post:
|
|
return Icons.image;
|
|
case ApiEnum.RequestAccepted:
|
|
return Icons.person;
|
|
case ApiEnum.CoachRequest:
|
|
return Icons.notifications;
|
|
case ApiEnum.ReportPost:
|
|
return Icons.report;
|
|
|
|
case ApiEnum.ChallengeCompleted:
|
|
return Icons.event;
|
|
case ApiEnum.GoalCompleted:
|
|
return Icons.fitness_center;
|
|
|
|
default:
|
|
return Icons.notifications;
|
|
}
|
|
}
|
|
|
|
Color getNotificationColor(int? notificationType) {
|
|
switch (notificationType) {
|
|
case ApiEnum.Goal:
|
|
return Colors.blue;
|
|
case ApiEnum.Challenge:
|
|
return Colors.orange;
|
|
case ApiEnum.ConnectionRequest:
|
|
return Colors.green;
|
|
case ApiEnum.Post:
|
|
return Colors.red;
|
|
case ApiEnum.RequestAccepted:
|
|
return Colors.purple;
|
|
case ApiEnum.CoachRequest:
|
|
return Colors.brown;
|
|
case ApiEnum.ReportPost:
|
|
return Colors.grey;
|
|
|
|
case ApiEnum.ChallengeCompleted:
|
|
return Colors.purpleAccent;
|
|
case ApiEnum.GoalCompleted:
|
|
return Colors.deepPurple;
|
|
default:
|
|
return Colors.grey;
|
|
}
|
|
}
|
|
}
|