Files
BudgetApp/lib/logic/user/user_cubit.dart
T
2025-07-16 21:00:30 +03:00

134 lines
5.3 KiB
Dart

import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:flutter/foundation.dart';
import 'package:logger/logger.dart';
import '/data/repositories/interfaces/icategory_repository.dart';
import '/data/repositories/interfaces/iglobal_settings_repository.dart';
import '/data/repositories/interfaces/itag_repository.dart';
import '/data/repositories/interfaces/itransaction_repository.dart';
import '/data/repositories/interfaces/iuser_repository.dart';
import '/models/user.dart';
import '/utils/category_utils.dart';
import '/utils/tag_utils.dart';
import '/utils/transaction_utils.dart';
part 'user_state.dart';
/// Cubit для управления состоянием пользователя.
/// Больше не управляет процессом входа, а только хранит состояние пользователя.
class UserCubit extends Cubit<UserState> {
final IGlobalSettingsRepository _settingsRepository;
final IUserRepository _userRepository;
// Эти репозитории теперь могут быть null и устанавливаются после входа пользователя.
ICategoryRepository? _categoryRepository;
ITagRepository? _tagRepository;
ITransactionRepository? _transactionRepository;
final Logger _logger = Logger(
printer: PrettyPrinter(
methodCount: 2, // Number of method calls to be displayed
errorMethodCount: 8, // Number of method calls if stacktrace is provided
lineLength: 120, // Width of the output
colors: true, // Colorful log messages
printEmojis: true, // Print an emoji for each log message
// Should each log print contain a timestamp
dateTimeFormat: DateTimeFormat.onlyTimeAndSinceStart,
),
);
UserCubit({
required IGlobalSettingsRepository settingsRepository,
required IUserRepository userRepository,
// Репозитории сделаны опциональными в конструкторе.
ICategoryRepository? categoryRepository,
ITagRepository? tagRepository,
ITransactionRepository? transactionRepository,
}) : _settingsRepository = settingsRepository,
_userRepository = userRepository,
_categoryRepository = categoryRepository,
_tagRepository = tagRepository,
_transactionRepository = transactionRepository,
super(UserInitial());
// Сеттеры для внедрения зависимостей после аутентификации.
set categoryRepository(ICategoryRepository? repo) => _categoryRepository = repo;
set tagRepository(ITagRepository? repo) => _tagRepository = repo;
set transactionRepository(ITransactionRepository? repo) =>
_transactionRepository = repo;
Future<void> createInitialData(String userId) async {
// Проверяем, что репозитории были установлены, прежде чем их использовать.
if (_categoryRepository == null ||
_tagRepository == null ||
_transactionRepository == null) {
_logger.w('User-specific repositories are not initialized. Skipping initial data creation.');
return;
}
try {
// Разбиваем создание данных на этапы
emit(UserLoading(progress: 0.7, message: 'Создание категорий...'));
// Используем '!', так как мы уже проверили на null.
await _categoryRepository!.addAll(
CategoryUtils.getDefaultCategories(),
);
emit(UserLoading(progress: 0.8, message: 'Создание тегов...'));
await _tagRepository!.addAll(TagUtils.getDefaultTags());
emit(UserLoading(progress: 0.9, message: 'Создание транзакций...'));
await _transactionRepository!.addAll(
TransactionUtils.getSampleTransactions(),
);
} catch (e, stack) {
_logger.e(
'Error creating initial data for user: $userId',
error: e,
stackTrace: stack,
);
}
}
/// Устанавливает текущего пользователя (прямая установка без загрузки)
void setUser(User user) {
emit(UserLoaded(user));
}
/// Выход из системы
Future<void> logout() async {
emit(UserLoading());
try {
await _settingsRepository.setCurrentUserId(null);
emit(UserLoaded(null));
} catch (e, stack) {
_logger.e('Error during logout', error: e, stackTrace: stack);
emit(UserError('Ошибка выхода из системы: ${e.toString()}'));
}
}
/// Возвращает всех пользователей
Future<List<User>> getAllUsers() async {
try {
return await _userRepository.getAll();
} catch (e, stack) {
_logger.e('Error getting all users', error: e, stackTrace: stack);
return [];
}
}
/// Обновляет данные пользователя
Future<void> updateUser(User updatedUser) async {
try {
if (state is UserLoaded) {
await _userRepository.update(updatedUser);
emit(UserLoaded(updatedUser));
_logger.i('User data updated successfully');
}
} catch (e, stack) {
_logger.e('Error updating user', error: e, stackTrace: stack);
throw Exception('Ошибка обновления пользователя');
}
}
}