Files
hackathon-sfc-a9a4cee231094…/lib/features/auth/presentation/bloc/auth_bloc.dart
2026-05-22 18:06:11 -06:00

89 lines
2.8 KiB
Dart

import 'package:flutter_bloc/flutter_bloc.dart';
import '../../data/repositories/auth_repository_impl.dart';
import '../../domain/usecases/auth_usecases.dart';
import 'auth_event.dart';
import 'auth_state.dart';
/// BLoC principal de autenticación.
///
/// Gestiona el ciclo de vida completo de la identidad del usuario:
/// verificación de sesión persistida → login → sesión activa → logout.
///
/// El token JWT simulado se almacena en el estado [AuthAuthenticated]
/// y estará disponible para inyectarse en headers HTTP en fases futuras.
class AuthBloc extends Bloc<AuthEvent, AuthState> {
final LoginUseCase _loginUseCase;
final LogoutUseCase _logoutUseCase;
final GetStoredSessionUseCase _getStoredSessionUseCase;
AuthBloc({
required LoginUseCase loginUseCase,
required LogoutUseCase logoutUseCase,
required GetStoredSessionUseCase getStoredSessionUseCase,
}) : _loginUseCase = loginUseCase,
_logoutUseCase = logoutUseCase,
_getStoredSessionUseCase = getStoredSessionUseCase,
super(const AuthInitial()) {
on<AuthSessionCheckRequested>(_onSessionCheckRequested);
on<AuthLoginRequested>(_onLoginRequested);
on<AuthLogoutRequested>(_onLogoutRequested);
}
/// Verifica si hay sesión activa al iniciar la app.
Future<void> _onSessionCheckRequested(
AuthSessionCheckRequested event,
Emitter<AuthState> emit,
) async {
emit(const AuthCheckingSession());
try {
final user = await _getStoredSessionUseCase.execute();
if (user != null) {
emit(AuthAuthenticated(user: user));
} else {
emit(const AuthUnauthenticated());
}
} catch (_) {
emit(const AuthUnauthenticated());
}
}
/// Procesa la solicitud de login con las credenciales del usuario.
Future<void> _onLoginRequested(
AuthLoginRequested event,
Emitter<AuthState> emit,
) async {
emit(const AuthLoading());
try {
final user = await _loginUseCase.execute(
identifier: event.identifier,
password: event.password,
);
emit(AuthAuthenticated(user: user));
} on AuthException catch (e) {
emit(AuthFailure(message: e.message, errorCode: e.code));
} on ArgumentError catch (e) {
emit(AuthFailure(message: e.message.toString()));
} catch (e) {
emit(const AuthFailure(
message: 'Error inesperado. Por favor intenta de nuevo.',
errorCode: 'UNKNOWN',
));
}
}
/// Cierra la sesión y limpia el estado local.
Future<void> _onLogoutRequested(
AuthLogoutRequested event,
Emitter<AuthState> emit,
) async {
emit(const AuthLoading());
try {
await _logoutUseCase.execute();
} finally {
// Siempre transiciona a no autenticado, incluso si falla la limpieza
emit(const AuthUnauthenticated());
}
}
}