import 'package:flutter/material.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'; 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 { WidgetsBinding.instance.addPostFrameCallback((_) { getNotifications(); getUnreadNotifications(); }); } bool _isLoading = false; String? _errorMessage; NotificationResponseModel? _notificationResponseModel; int currentPage = 1; static const int _pageSize = 10; int _totalPages = 0; bool _hasMoreData = true; bool get isLoading => _isLoading; String? get errorMessage => _errorMessage; NotificationResponseModel? get notificationResponse => _notificationResponseModel; bool get hasMoreData => _hasMoreData; int get totalPages => _totalPages; NotificationResponseModel? _unreadNotificationResponse; bool _isUnreadLoading = false; NotificationResponseModel? get unreadNotificationResponse => _unreadNotificationResponse; bool get isUnreadLoading => _isUnreadLoading; /// Fetch notifications Future getNotifications({int page = 1, bool isMobile = false}) async { _isLoading = true; notifyListeners(); final int offset = _pageSize * page; final result = await _repository.getNotifications( limit: _pageSize, offset: offset, ); switch (result) { case Ok(): if (isMobile && page > 1) { final oldNotifications = _notificationResponseModel?.data?.notifications ?? []; final newNotifications = result.value.data?.notifications ?? []; _notificationResponseModel = result.value.copyWith( data: result.value.data?.copyWith( notifications: [...oldNotifications, ...newNotifications], ), ); } else { _notificationResponseModel = result.value; } currentPage = page; _hasMoreData = (result.value.data?.notifications?.length ?? 0) >= _pageSize; _totalPages = result.value.data?.meta?.pages ?? 1; break; case Error(): _errorMessage = result.error.toString(); break; } _isLoading = false; notifyListeners(); } /// Jump to page Future jumpToPage(int page) async { if (_totalPages == 0 || page < 1 || page > _totalPages) { return; } await getNotifications(page: page); } /// Mark all as read Future markAllAsRead(BuildContext context) async { _isLoading = true; _errorMessage = null; notifyListeners(); final result = await _repository.markAllAsRead(); if (!context.mounted) { return; } switch (result) { case Ok>(): final response = result.value; final success = response['success'] as bool? ?? false; final message = response['message'] as String? ?? NotificationStrings.unknownResponse; if (success) { if (_notificationResponseModel?.data?.notifications != null) { final updatedNotifications = _notificationResponseModel!.data!.notifications! .map((n) => n.copyWith(seen: true)) .toList(); _notificationResponseModel = _notificationResponseModel!.copyWith( data: _notificationResponseModel!.data!.copyWith( notifications: updatedNotifications, ), ); } await getNotifications(page: currentPage); await getUnreadNotifications(); if (context.mounted) { AppToast.success( context, NotificationStrings.allNotificationMarkedAsRead, ); } } else { _errorMessage = message; if (context.mounted) { AppToast.error(context, message); } } break; case Error>(): _errorMessage = result.error.toString(); if (context.mounted) { AppToast.error(context, _errorMessage!); } break; } _isLoading = false; notifyListeners(); } String timeAgo(String dateTimeString) { final createdAt = DateTime.parse(dateTimeString); final now = DateTime.now(); final difference = now.difference(createdAt); if (difference.inMinutes < 1) { return NotificationStrings.now; } else if (difference.inMinutes < 60) { return '${difference.inMinutes} ${NotificationStrings.min} '; } else if (difference.inHours < 24) { return '${difference.inHours} ${NotificationStrings.hour} '; } else if (difference.inDays == 1) { return NotificationStrings.yesterday; } else { return '${difference.inDays} ${NotificationStrings.daysAgo}'; } } Future getUnreadNotifications({int page = 1}) async { _isUnreadLoading = true; notifyListeners(); final int offset = _pageSize * page; final result = await _repository.getUnreadNotifications( limit: _pageSize, offset: offset, ); switch (result) { case Ok(): _unreadNotificationResponse = result.value; break; case Error(): _errorMessage = result.error.toString(); break; } _isUnreadLoading = false; notifyListeners(); } }