feat: integrate ErrorService for consistent error display and standardize bloc error messages.
This commit is contained in:
@@ -22,43 +22,46 @@
|
||||
/// Example usage:
|
||||
/// ```dart
|
||||
/// final tripBloc = TripBloc(tripRepository);
|
||||
///
|
||||
///
|
||||
/// // Load trips for a user
|
||||
/// tripBloc.add(LoadTripsByUserId(userId: 'userId123'));
|
||||
///
|
||||
///
|
||||
/// // Create a new trip
|
||||
/// tripBloc.add(TripCreateRequested(trip: newTrip));
|
||||
///
|
||||
///
|
||||
/// // Update a trip
|
||||
/// tripBloc.add(TripUpdateRequested(trip: updatedTrip));
|
||||
///
|
||||
///
|
||||
/// // Delete a trip
|
||||
/// tripBloc.add(TripDeleteRequested(tripId: 'tripId456'));
|
||||
/// ```
|
||||
library;
|
||||
|
||||
import 'dart:async';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:travel_mate/models/trip.dart';
|
||||
import 'trip_event.dart';
|
||||
import 'trip_state.dart';
|
||||
import '../../repositories/trip_repository.dart';
|
||||
import '../../services/error_service.dart';
|
||||
|
||||
/// BLoC that manages trip-related operations and state.
|
||||
class TripBloc extends Bloc<TripEvent, TripState> {
|
||||
/// Repository for trip data operations
|
||||
final TripRepository _repository;
|
||||
|
||||
final _errorService = ErrorService();
|
||||
|
||||
/// Subscription to trip stream for real-time updates
|
||||
StreamSubscription? _tripsSubscription;
|
||||
|
||||
|
||||
/// Current user ID for automatic list refreshing after operations
|
||||
String? _currentUserId;
|
||||
|
||||
/// Constructor for TripBloc.
|
||||
///
|
||||
///
|
||||
/// Initializes the bloc with the trip repository and sets up event handlers
|
||||
/// for all trip-related operations.
|
||||
///
|
||||
///
|
||||
/// Args:
|
||||
/// [_repository]: Repository for trip data operations
|
||||
TripBloc(this._repository) : super(TripInitial()) {
|
||||
@@ -71,11 +74,11 @@ class TripBloc extends Bloc<TripEvent, TripState> {
|
||||
}
|
||||
|
||||
/// Handles [LoadTripsByUserId] events.
|
||||
///
|
||||
///
|
||||
/// Loads all trips for a specific user with real-time updates via stream subscription.
|
||||
/// Stores the user ID for future automatic refreshing after operations and cancels
|
||||
/// any existing subscription to prevent memory leaks.
|
||||
///
|
||||
///
|
||||
/// Args:
|
||||
/// [event]: The LoadTripsByUserId event containing the user ID
|
||||
/// [emit]: State emitter function
|
||||
@@ -84,41 +87,45 @@ class TripBloc extends Bloc<TripEvent, TripState> {
|
||||
Emitter<TripState> emit,
|
||||
) async {
|
||||
emit(TripLoading());
|
||||
|
||||
|
||||
_currentUserId = event.userId;
|
||||
await _tripsSubscription?.cancel();
|
||||
|
||||
_tripsSubscription = _repository.getTripsByUserId(event.userId).listen(
|
||||
(trips) {
|
||||
add(_TripsUpdated(trips));
|
||||
},
|
||||
onError: (error) {
|
||||
emit(TripError(error.toString()));
|
||||
},
|
||||
);
|
||||
_tripsSubscription = _repository
|
||||
.getTripsByUserId(event.userId)
|
||||
.listen(
|
||||
(trips) {
|
||||
add(_TripsUpdated(trips));
|
||||
},
|
||||
onError: (error, stackTrace) {
|
||||
_errorService.logError(
|
||||
'TripBloc',
|
||||
'Error loading trips: $error',
|
||||
stackTrace,
|
||||
);
|
||||
emit(const TripError('Impossible de charger les voyages'));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Handles [_TripsUpdated] events.
|
||||
///
|
||||
///
|
||||
/// Processes real-time updates from the trip stream and emits the
|
||||
/// updated trip list to the UI.
|
||||
///
|
||||
///
|
||||
/// Args:
|
||||
/// [event]: The _TripsUpdated event containing the updated trip list
|
||||
/// [emit]: State emitter function
|
||||
void _onTripsUpdated(
|
||||
_TripsUpdated event,
|
||||
Emitter<TripState> emit,
|
||||
) {
|
||||
void _onTripsUpdated(_TripsUpdated event, Emitter<TripState> emit) {
|
||||
emit(TripLoaded(event.trips));
|
||||
}
|
||||
|
||||
/// Handles [TripCreateRequested] events.
|
||||
///
|
||||
///
|
||||
/// Creates a new trip and automatically refreshes the user's trip list
|
||||
/// to show the newly created trip. Includes a delay to allow the creation
|
||||
/// to complete before refreshing.
|
||||
///
|
||||
///
|
||||
/// Args:
|
||||
/// [event]: The TripCreateRequested event containing the trip data
|
||||
/// [emit]: State emitter function
|
||||
@@ -128,27 +135,27 @@ class TripBloc extends Bloc<TripEvent, TripState> {
|
||||
) async {
|
||||
try {
|
||||
emit(TripLoading());
|
||||
|
||||
|
||||
final tripId = await _repository.createTrip(event.trip);
|
||||
|
||||
|
||||
emit(TripCreated(tripId: tripId));
|
||||
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 800));
|
||||
if (_currentUserId != null) {
|
||||
add(LoadTripsByUserId(userId: _currentUserId!));
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
emit(TripError('Error during creation: $e'));
|
||||
} catch (e, stackTrace) {
|
||||
_errorService.logError('TripBloc', 'Error creating trip: $e', stackTrace);
|
||||
emit(const TripError('Impossible de créer le voyage'));
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles [TripUpdateRequested] events.
|
||||
///
|
||||
///
|
||||
/// Updates an existing trip and automatically refreshes the user's trip list
|
||||
/// to show the updated information. Includes a delay to allow the update
|
||||
/// to complete before refreshing.
|
||||
///
|
||||
///
|
||||
/// Args:
|
||||
/// [event]: The TripUpdateRequested event containing the updated trip data
|
||||
/// [emit]: State emitter function
|
||||
@@ -163,18 +170,18 @@ class TripBloc extends Bloc<TripEvent, TripState> {
|
||||
if (_currentUserId != null) {
|
||||
add(LoadTripsByUserId(userId: _currentUserId!));
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
emit(TripError('Error during update: $e'));
|
||||
} catch (e, stackTrace) {
|
||||
_errorService.logError('TripBloc', 'Error updating trip: $e', stackTrace);
|
||||
emit(const TripError('Impossible de mettre à jour le voyage'));
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles [TripDeleteRequested] events.
|
||||
///
|
||||
///
|
||||
/// Deletes a trip and automatically refreshes the user's trip list
|
||||
/// to remove the deleted trip from the UI. Includes a delay to allow
|
||||
/// the deletion to complete before refreshing.
|
||||
///
|
||||
///
|
||||
/// Args:
|
||||
/// [event]: The TripDeleteRequested event containing the trip ID to delete
|
||||
/// [emit]: State emitter function
|
||||
@@ -184,39 +191,36 @@ class TripBloc extends Bloc<TripEvent, TripState> {
|
||||
) async {
|
||||
try {
|
||||
await _repository.deleteTrip(event.tripId);
|
||||
|
||||
|
||||
emit(const TripOperationSuccess('Trip deleted successfully'));
|
||||
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
if (_currentUserId != null) {
|
||||
add(LoadTripsByUserId(userId: _currentUserId!));
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
emit(TripError('Error during deletion: $e'));
|
||||
} catch (e, stackTrace) {
|
||||
_errorService.logError('TripBloc', 'Error deleting trip: $e', stackTrace);
|
||||
emit(const TripError('Impossible de supprimer le voyage'));
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles [ResetTrips] events.
|
||||
///
|
||||
///
|
||||
/// Resets the trip state to initial and cleans up resources.
|
||||
/// Cancels the trip stream subscription and clears the current user ID.
|
||||
/// This is useful for user logout or when switching contexts.
|
||||
///
|
||||
///
|
||||
/// Args:
|
||||
/// [event]: The ResetTrips event
|
||||
/// [emit]: State emitter function
|
||||
Future<void> _onResetTrips(
|
||||
ResetTrips event,
|
||||
Emitter<TripState> emit,
|
||||
) async {
|
||||
Future<void> _onResetTrips(ResetTrips event, Emitter<TripState> emit) async {
|
||||
await _tripsSubscription?.cancel();
|
||||
_currentUserId = null;
|
||||
emit(TripInitial());
|
||||
}
|
||||
|
||||
/// Cleans up resources when the bloc is closed.
|
||||
///
|
||||
///
|
||||
/// Cancels the trip stream subscription to prevent memory leaks
|
||||
/// and ensure proper disposal of resources.
|
||||
@override
|
||||
@@ -227,7 +231,7 @@ class TripBloc extends Bloc<TripEvent, TripState> {
|
||||
}
|
||||
|
||||
/// Private event for handling real-time trip updates from streams.
|
||||
///
|
||||
///
|
||||
/// This internal event is used to process updates from the trip stream
|
||||
/// subscription and emit appropriate states based on the received data.
|
||||
class _TripsUpdated extends TripEvent {
|
||||
@@ -235,11 +239,11 @@ class _TripsUpdated extends TripEvent {
|
||||
final List<Trip> trips;
|
||||
|
||||
/// Creates a _TripsUpdated event.
|
||||
///
|
||||
///
|
||||
/// Args:
|
||||
/// [trips]: List of trips from the stream update
|
||||
const _TripsUpdated(this.trips);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [trips];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user