it0/it0_app/lib/features/settings/presentation/providers/settings_providers.dart

211 lines
6.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../../../core/network/dio_client.dart';
import '../../data/datasources/settings_datasource.dart';
import '../../data/datasources/settings_remote_datasource.dart';
import '../../data/repositories/settings_repository_impl.dart';
import '../../domain/entities/app_settings.dart';
import '../../domain/repositories/settings_repository.dart';
// ---------------------------------------------------------------------------
// Dependency providers
// ---------------------------------------------------------------------------
final _sharedPreferencesProvider = FutureProvider<SharedPreferences>((ref) {
return SharedPreferences.getInstance();
});
final settingsDatasourceProvider = Provider<SettingsDatasource?>((ref) {
final prefsAsync = ref.watch(_sharedPreferencesProvider);
return prefsAsync.whenOrNull(
data: (prefs) => SettingsDatasource(prefs),
);
});
final settingsRepositoryProvider = Provider<SettingsRepository?>((ref) {
final datasource = ref.watch(settingsDatasourceProvider);
if (datasource == null) return null;
return SettingsRepositoryImpl(datasource);
});
final settingsRemoteDatasourceProvider =
Provider<SettingsRemoteDatasource>((ref) {
final dio = ref.watch(dioClientProvider);
return SettingsRemoteDatasource(dio);
});
// ---------------------------------------------------------------------------
// Account profile state
// ---------------------------------------------------------------------------
class AccountProfile {
final String displayName;
final String email;
final bool isLoading;
final String? error;
const AccountProfile({
this.displayName = '',
this.email = '',
this.isLoading = false,
this.error,
});
AccountProfile copyWith({
String? displayName,
String? email,
bool? isLoading,
String? error,
}) {
return AccountProfile(
displayName: displayName ?? this.displayName,
email: email ?? this.email,
isLoading: isLoading ?? this.isLoading,
error: error,
);
}
}
// ---------------------------------------------------------------------------
// Settings state notifier
// ---------------------------------------------------------------------------
class SettingsNotifier extends StateNotifier<AppSettings> {
final SettingsRepository? _repository;
SettingsNotifier(this._repository) : super(const AppSettings()) {
_loadSettings();
}
Future<void> _loadSettings() async {
if (_repository == null) return;
try {
final settings = await _repository.loadSettings();
state = settings;
} catch (_) {
// Use defaults on error
}
}
Future<void> setThemeMode(ThemeMode mode) async {
state = state.copyWith(themeMode: mode);
await _repository?.saveSettings(state);
}
Future<void> setNotificationsEnabled(bool enabled) async {
state = state.copyWith(notificationsEnabled: enabled);
await _repository?.saveSettings(state);
}
Future<void> setSoundEnabled(bool enabled) async {
state = state.copyWith(soundEnabled: enabled);
await _repository?.saveSettings(state);
}
Future<void> setHapticFeedback(bool enabled) async {
state = state.copyWith(hapticFeedback: enabled);
await _repository?.saveSettings(state);
}
Future<void> setTenant(String? id, String? name) async {
state = state.copyWith(selectedTenantId: id, selectedTenantName: name);
await _repository?.saveSettings(state);
}
Future<void> setLanguage(String language) async {
state = state.copyWith(language: language);
await _repository?.saveSettings(state);
}
Future<void> setBiometricEnabled(bool enabled) async {
state = state.copyWith(biometricEnabled: enabled);
await _repository?.saveSettings(state);
}
Future<void> resetToDefaults() async {
await _repository?.resetSettings();
state = const AppSettings();
}
}
// ---------------------------------------------------------------------------
// Account profile notifier
// ---------------------------------------------------------------------------
class AccountProfileNotifier extends StateNotifier<AccountProfile> {
final SettingsRemoteDatasource _remote;
AccountProfileNotifier(this._remote) : super(const AccountProfile());
Future<void> loadProfile() async {
state = state.copyWith(isLoading: true, error: null);
try {
final data = await _remote.getAccount();
state = state.copyWith(
displayName: data['displayName'] as String? ?? '',
email: data['email'] as String? ?? '',
isLoading: false,
);
} catch (e) {
state = state.copyWith(isLoading: false, error: e.toString());
}
}
Future<bool> updateDisplayName(String name) async {
state = state.copyWith(isLoading: true, error: null);
try {
final data = await _remote.updateAccount(name);
state = state.copyWith(
displayName: data['displayName'] as String? ?? name,
isLoading: false,
);
return true;
} catch (e) {
state = state.copyWith(isLoading: false, error: e.toString());
return false;
}
}
Future<({bool success, String? message})> changePassword({
required String currentPassword,
required String newPassword,
}) async {
try {
final data = await _remote.changePassword(
currentPassword: currentPassword,
newPassword: newPassword,
);
final success = data['success'] as bool? ?? false;
final message = data['message'] as String?;
return (success: success, message: message);
} catch (e) {
return (success: false, message: e.toString());
}
}
}
// ---------------------------------------------------------------------------
// Main providers
// ---------------------------------------------------------------------------
final settingsProvider =
StateNotifierProvider<SettingsNotifier, AppSettings>((ref) {
final repository = ref.watch(settingsRepositoryProvider);
return SettingsNotifier(repository);
});
final accountProfileProvider =
StateNotifierProvider<AccountProfileNotifier, AccountProfile>((ref) {
final remote = ref.watch(settingsRemoteDatasourceProvider);
return AccountProfileNotifier(remote);
});
final themeModeProvider = Provider<ThemeMode>((ref) {
return ref.watch(settingsProvider).themeMode;
});
final notificationsEnabledProvider = Provider<bool>((ref) {
return ref.watch(settingsProvider).notificationsEnabled;
});