You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cloudsolutions-atoms/lib/modules/notification_setting/provider/notification_setting_provid...

237 lines
6.8 KiB
Dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/modules/notification_setting/models/notification_preference_model.dart';
class NotificationSettingProvider extends ChangeNotifier {
// State management
bool _isLoading = false;
bool _isLoadingMore = false;
bool _isSaving = false;
String? _errorMessage;
List<NotificationTemplate> _templates = [];
// Pagination
int _currentPage = 1;
final int _pageSize = 10;
int _totalRecords = 0;
bool _hasMoreData = true;
// Getters
bool get isLoading => _isLoading;
bool get isLoadingMore => _isLoadingMore;
bool get isSaving => _isSaving;
String? get errorMessage => _errorMessage;
List<NotificationTemplate> get templates => _templates;
bool get hasMoreData => _hasMoreData;
bool get isEmpty => _templates.isEmpty && !_isLoading;
// Check if there are any modified templates
bool get hasChanges => _templates.any((template) => template.isModified);
/// Load initial notification preferences
Future<void> loadNotificationPreferences({bool refresh = false}) async {
if (refresh) {
reset();
}
if (_isLoading || _isLoadingMore) return;
_isLoading = _currentPage == 1;
_errorMessage = null;
notifyListeners();
try {
final body = {
'pageNumber': _currentPage,
'pageSize': _pageSize,
};
http.Response response = await ApiManager.instance.post(
URLs.getNotificationPreferences,
body: body,
showToast: false,
);
if (response.statusCode >= 200 && response.statusCode < 300) {
final jsonData = json.decode(response.body);
final notificationResponse = NotificationPreferenceResponse.fromJson(jsonData);
if (notificationResponse.isSuccess == true && notificationResponse.data != null) {
_totalRecords = notificationResponse.totalRows ?? 0;
if (notificationResponse.data!.isNotEmpty) {
_templates.addAll(notificationResponse.data!);
_currentPage++;
_hasMoreData = _templates.length < _totalRecords;
} else {
_hasMoreData = false;
}
} else {
_errorMessage = notificationResponse.message ?? 'Failed to load notification preferences';
_hasMoreData = false;
}
} else {
_errorMessage = 'Failed to load notification preferences';
_hasMoreData = false;
}
} catch (error) {
_errorMessage = 'An error occurred while loading data';
print('Error in loadNotificationPreferences: $error');
} finally {
_isLoading = false;
notifyListeners();
}
}
/// Load more data for pagination
Future<void> loadMoreData() async {
if (_isLoadingMore || !_hasMoreData || _isLoading) return;
_isLoadingMore = true;
notifyListeners();
try {
final body = {
'pageNumber': _currentPage,
'pageSize': _pageSize,
};
http.Response response = await ApiManager.instance.post(
URLs.getNotificationPreferences,
body: body,
showToast: false,
);
if (response.statusCode >= 200 && response.statusCode < 300) {
final jsonData = json.decode(response.body);
final notificationResponse = NotificationPreferenceResponse.fromJson(jsonData);
if (notificationResponse.isSuccess == true && notificationResponse.data != null) {
if (notificationResponse.data!.isNotEmpty) {
_templates.addAll(notificationResponse.data!);
_currentPage++;
_hasMoreData = _templates.length < _totalRecords;
} else {
_hasMoreData = false;
}
} else {
_hasMoreData = false;
}
} else {
_hasMoreData = false;
}
} catch (error) {
print('Error in loadMoreData: $error');
} finally {
_isLoadingMore = false;
notifyListeners();
}
}
/// Update enable/disable state for a template
void updateTemplateState(int index, bool isDisabled) {
if (index < 0 || index >= _templates.length) {
return;
}
final template = _templates[index];
// Note: mandatory flag only applies to channel preferences, not to enable/disable toggle
// Users can always enable/disable notifications
_templates[index] = template.copyWith(
isDisabled: isDisabled,
isModified: true,
);
notifyListeners();
}
/// Update selected channels for a template
void updateTemplateChannels(int index, List<int> channelIds) {
if (index < 0 || index >= _templates.length) return;
final template = _templates[index];
_templates[index] = template.copyWith(
selectedChannelIds: channelIds,
isModified: true,
);
_templates[index].selectedChannelIds = channelIds;
notifyListeners();
}
/// Save all modified preferences
Future<bool> savePreferences() async {
if (!hasChanges) return true;
_isSaving = true;
_errorMessage = null;
notifyListeners();
try {
final preferences = _templates.where((t) => t.isModified).map((template) {
return {
'notificationTemplateId': template.notificationTemplateId,
'disabled': template.isDisabled ?? false,
'channels': template.selectedChannelIds,
};
}).toList();
if (preferences.isEmpty) {
_isSaving = false;
notifyListeners();
return true;
}
// Use ApiManager's postList method for array body
http.Response response = await ApiManager.instance.postList(
URLs.saveNotificationPreferences,
body: preferences,
showToast: true,
);
if (response.statusCode >= 200 && response.statusCode < 300) {
// Reset modification flags after successful save
for (var i = 0; i < _templates.length; i++) {
_templates[i] = _templates[i].copyWith(isModified: false);
}
_isSaving = false;
notifyListeners();
return true;
} else {
_errorMessage = 'Failed to save preferences';
_isSaving = false;
notifyListeners();
return false;
}
} catch (error) {
_errorMessage = 'An error occurred while saving';
_isSaving = false;
notifyListeners();
print('Error in savePreferences: $error');
return false;
}
}
/// Reset provider state
void reset() {
_templates.clear();
_currentPage = 1;
_hasMoreData = true;
_totalRecords = 0;
_isLoading = false;
_isLoadingMore = false;
_errorMessage = null;
}
/// Retry loading after error
Future<void> retry() async {
reset();
await loadNotificationPreferences();
}
}