Files
TravelMate/lib/blocs/account/account_bloc.dart

127 lines
3.9 KiB
Dart

/// A BLoC (Business Logic Component) that manages account-related state and operations.
///
/// This bloc handles account operations such as loading accounts by user ID,
/// creating new accounts, and managing real-time updates from the account repository.
/// It uses stream subscriptions to listen for account changes and emits corresponding states.
///
/// The bloc supports the following operations:
/// - Loading accounts by user ID with real-time updates
/// - Creating a single account without members
/// - Creating an account with associated members
///
/// All errors are logged using [ErrorService] and emitted as [AccountError] states.
///
/// Example usage:
/// ```dart
/// final accountBloc = AccountBloc(accountRepository);
/// accountBloc.add(LoadAccountsByUserId('user123'));
/// ```
///
/// Remember to close the bloc when done to cancel active subscriptions:
/// ```dart
/// accountBloc.close();
/// ```
library;
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:travel_mate/services/error_service.dart';
import 'account_event.dart';
import 'account_state.dart';
import '../../repositories/account_repository.dart';
import '../../models/account.dart';
class AccountBloc extends Bloc<AccountEvent, AccountState> {
final AccountRepository _repository;
StreamSubscription? _accountsSubscription;
final _errorService = ErrorService();
AccountBloc(this._repository) : super(AccountInitial()) {
on<LoadAccountsByUserId>(_onLoadAccountsByUserId);
on<_AccountsUpdated>(_onAccountsUpdated);
on<CreateAccount>(_onCreateAccount);
on<CreateAccountWithMembers>(_onCreateAccountWithMembers);
}
Future<void> _onLoadAccountsByUserId(
LoadAccountsByUserId event,
Emitter<AccountState> emit,
) async {
try {
emit(AccountLoading());
await _accountsSubscription?.cancel();
_accountsSubscription = _repository.getAccountByUserId(event.userId).listen(
(accounts) {
add(_AccountsUpdated(accounts));
},
onError: (error) {
add(_AccountsUpdated([], error: error.toString()));
},
);
} catch (e, stackTrace) {
_errorService.logError(e.toString(), stackTrace);
emit(AccountError(e.toString()));
}
}
Future<void> _onAccountsUpdated(
_AccountsUpdated event,
Emitter<AccountState> emit,
) async {
if (event.error != null) {
_errorService.logError(event.error!, StackTrace.current);
emit(AccountError(event.error!));
} else {
emit(AccountsLoaded(event.accounts));
}
}
Future<void> _onCreateAccount(
CreateAccount event,
Emitter<AccountState> emit,
) async {
try {
emit(AccountLoading());
final accountId = await _repository.createAccountWithMembers(
account: event.account,
members: [],
);
emit(AccountOperationSuccess('Compte créé avec succès. ID: $accountId'));
} catch (e, stackTrace) {
_errorService.logError(e.toString(), stackTrace);
emit(AccountError('Erreur lors de la création du compte: ${e.toString()}'));
}
}
Future<void> _onCreateAccountWithMembers(
CreateAccountWithMembers event,
Emitter<AccountState> emit,
) async {
try{
emit(AccountLoading());
final accountId = await _repository.createAccountWithMembers(
account: event.account,
members: event.members,
);
emit(AccountOperationSuccess('Compte créé avec succès. ID: $accountId'));
} catch (e, stackTrace) {
_errorService.logError(e.toString(), stackTrace);
emit(AccountError('Erreur lors de la création du compte: ${e.toString()}'));
}
}
@override
Future<void> close() {
_accountsSubscription?.cancel();
return super.close();
}
}
class _AccountsUpdated extends AccountEvent {
final List<Account> accounts;
final String? error;
const _AccountsUpdated(this.accounts, {this.error});
@override
List<Object?> get props => [accounts, error];
}