/// 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 { final AccountRepository _repository; StreamSubscription? _accountsSubscription; final _errorService = ErrorService(); AccountBloc(this._repository) : super(AccountInitial()) { on(_onLoadAccountsByUserId); on<_AccountsUpdated>(_onAccountsUpdated); on(_onCreateAccount); on(_onCreateAccountWithMembers); on(_onAddMemberToAccount); on(_onRemoveMemberFromAccount); } Future _onLoadAccountsByUserId( LoadAccountsByUserId event, Emitter 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( 'AccountBloc', 'Error loading accounts: $e', stackTrace, ); emit(const AccountError('Impossible de charger les comptes')); } } Future _onAccountsUpdated( _AccountsUpdated event, Emitter emit, ) async { if (event.error != null) { _errorService.logError(event.error!, StackTrace.current); emit(AccountError(event.error!)); } else { emit(AccountsLoaded(event.accounts)); } } Future _onCreateAccount( CreateAccount event, Emitter 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( 'AccountBloc', 'Error creating account: $e', stackTrace, ); emit(const AccountError('Impossible de créer le compte')); } } Future _onCreateAccountWithMembers( CreateAccountWithMembers event, Emitter 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( 'AccountBloc', 'Error creating account with members: $e', stackTrace, ); emit(const AccountError('Impossible de créer le compte')); } } Future _onAddMemberToAccount( AddMemberToAccount event, Emitter emit, ) async { try { emit(AccountLoading()); await _repository.addMemberToAccount(event.accountId, event.member); emit(AccountOperationSuccess('Membre ajouté avec succès')); } catch (e, stackTrace) { _errorService.logError( 'AccountBloc', 'Error adding member: $e', stackTrace, ); emit(const AccountError('Impossible d\'ajouter le membre')); } } Future _onRemoveMemberFromAccount( RemoveMemberFromAccount event, Emitter emit, ) async { try { emit(AccountLoading()); await _repository.removeMemberFromAccount( event.accountId, event.memberId, ); emit(AccountOperationSuccess('Membre supprimé avec succès')); } catch (e, stackTrace) { _errorService.logError( 'AccountBloc', 'Error removing member: $e', stackTrace, ); emit(const AccountError('Impossible de supprimer le membre')); } } @override Future close() { _accountsSubscription?.cancel(); return super.close(); } } class _AccountsUpdated extends AccountEvent { final List accounts; final String? error; const _AccountsUpdated(this.accounts, {this.error}); @override List get props => [accounts, error]; }