184 lines
5.3 KiB
Dart
184 lines
5.3 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);
|
|
on<AddMemberToAccount>(_onAddMemberToAccount);
|
|
on<RemoveMemberFromAccount>(_onRemoveMemberFromAccount);
|
|
}
|
|
|
|
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(
|
|
'AccountBloc',
|
|
'Error loading accounts: $e',
|
|
stackTrace,
|
|
);
|
|
emit(const AccountError('Impossible de charger les comptes'));
|
|
}
|
|
}
|
|
|
|
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(
|
|
'AccountBloc',
|
|
'Error creating account: $e',
|
|
stackTrace,
|
|
);
|
|
emit(const AccountError('Impossible de créer le compte'));
|
|
}
|
|
}
|
|
|
|
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(
|
|
'AccountBloc',
|
|
'Error creating account with members: $e',
|
|
stackTrace,
|
|
);
|
|
emit(const AccountError('Impossible de créer le compte'));
|
|
}
|
|
}
|
|
|
|
Future<void> _onAddMemberToAccount(
|
|
AddMemberToAccount event,
|
|
Emitter<AccountState> 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<void> _onRemoveMemberFromAccount(
|
|
RemoveMemberFromAccount event,
|
|
Emitter<AccountState> 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<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];
|
|
}
|