Files
TravelMate/lib/blocs/user/user_bloc.dart
Dayron 2faf37f145 Enhance model and service documentation with detailed comments and descriptions
- Updated Group, Trip, User, and other model classes to include comprehensive documentation for better understanding and maintainability.
- Improved error handling and logging in services, including AuthService, ErrorService, and StorageService.
- Added validation and business logic explanations in ExpenseService and TripService.
- Refactored method comments to follow a consistent format across the codebase.
- Translated error messages and comments from French to English for consistency.
2025-10-30 15:56:17 +01:00

156 lines
4.8 KiB
Dart

import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'user_event.dart' as event;
import 'user_state.dart' as state;
/// BLoC for managing user data and operations.
///
/// This BLoC handles user-related operations including loading user data,
/// updating user information, and managing user state throughout the application.
/// It coordinates with Firebase Auth and Firestore to manage user data persistence.
class UserBloc extends Bloc<event.UserEvent, state.UserState> {
/// Firebase Auth instance for authentication operations.
final FirebaseAuth _auth = FirebaseAuth.instance;
/// Firestore instance for user data operations.
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
/// Creates a new [UserBloc] with initial state.
///
/// Registers event handlers for all user-related events.
UserBloc() : super(state.UserInitial()) {
on<event.UserInitialized>(_onUserInitialized);
on<event.LoadUser>(_onLoadUser);
on<event.UserUpdated>(_onUserUpdated);
on<event.UserLoggedOut>(_onUserLoggedOut);
}
/// Handles [UserInitialized] events.
///
/// Initializes the current authenticated user's data by fetching it from Firestore.
/// If the user doesn't exist in Firestore, creates a default user document.
/// This is typically called when the app starts or after successful authentication.
Future<void> _onUserInitialized(
event.UserInitialized event,
Emitter<state.UserState> emit,
) async {
emit(state.UserLoading());
try {
final currentUser = _auth.currentUser;
if (currentUser == null) {
emit(state.UserError('No user currently authenticated'));
return;
}
// Fetch user data from Firestore
final userDoc = await _firestore
.collection('users')
.doc(currentUser.uid)
.get();
if (!userDoc.exists) {
// Create a default user if it doesn't exist
final defaultUser = state.UserModel(
id: currentUser.uid,
email: currentUser.email ?? '',
prenom: currentUser.displayName ?? 'Voyageur',
);
await _firestore
.collection('users')
.doc(currentUser.uid)
.set(defaultUser.toJson());
emit(state.UserLoaded(defaultUser));
} else {
final user = state.UserModel.fromJson({
'id': currentUser.uid,
...userDoc.data()!,
});
emit(state.UserLoaded(user));
}
} catch (e) {
emit(state.UserError('Error loading user: $e'));
}
}
/// Handles [LoadUser] events.
///
/// Loads a specific user's data from Firestore by their user ID.
/// This is useful when you need to display information about other users.
Future<void> _onLoadUser(
event.LoadUser event,
Emitter<state.UserState> emit,
) async {
emit(state.UserLoading());
try {
final userDoc = await _firestore
.collection('users')
.doc(event.userId)
.get();
if (userDoc.exists) {
final user = state.UserModel.fromJson({
'id': event.userId,
...userDoc.data()!,
});
emit(state.UserLoaded(user));
} else {
emit(state.UserError('User not found'));
}
} catch (e) {
emit(state.UserError('Error loading user: $e'));
}
}
/// Handles [UserUpdated] events.
///
/// Updates the current user's data in Firestore with the provided information.
/// Only updates the fields specified in the userData map, allowing for partial updates.
/// After successful update, reloads the user data to reflect changes.
Future<void> _onUserUpdated(
event.UserUpdated event,
Emitter<state.UserState> emit,
) async {
if (this.state is state.UserLoaded) {
final currentUser = (this.state as state.UserLoaded).user;
try {
await _firestore
.collection('users')
.doc(currentUser.id)
.update(event.userData);
final updatedDoc = await _firestore
.collection('users')
.doc(currentUser.id)
.get();
final updatedUser = state.UserModel.fromJson({
'id': currentUser.id,
...updatedDoc.data()!,
});
emit(state.UserLoaded(updatedUser));
} catch (e) {
emit(state.UserError('Error updating user: $e'));
}
}
}
/// Handles [UserLoggedOut] events.
///
/// Resets the user bloc state to initial when the user logs out.
/// This clears any cached user data from the application state.
Future<void> _onUserLoggedOut(
event.UserLoggedOut event,
Emitter<state.UserState> emit,
) async {
emit(state.UserInitial());
}
}