feat: implement SMS OTP auth via backend API

- signInWithPhoneNumber: calls POST /auth/send-otp, stores pending phone
- verifyOTP: calls POST /auth/phone with phone+code, saves token
- linkWithOTP: calls POST /auth/verify-phone (authenticated) with phone+code
- AuthBloc._linkWithPhoneNumber: replaced Firebase PhoneVerificationService with repository call

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-06-25 15:23:39 -05:00
co-authored by Claude Sonnet 4.6
parent 7446f22e23
commit 38beca4b4f
2 changed files with 54 additions and 46 deletions
+4 -36
View File
@@ -9,9 +9,6 @@ part 'auth_state.dart';
class AuthBloc extends Bloc<AuthEvent, AuthState> {
final UserRepository _userRepository;
final PhoneVerificationService phoneVerificationService =
PhoneVerificationService();
String? _verificationId;
AuthBloc({required UserRepository userRepository})
: _userRepository = userRepository,
@@ -103,39 +100,11 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
void _linkWithPhoneNumber(
LinkWithPhoneNumber event, Emitter<AuthState> emit) async {
emit(AuthStateProcess());
try {
await for (PhoneAuthEvent event
in phoneVerificationService.verifyPhoneNumber(event.phoneNumber)) {
switch (event.type) {
case PhoneAuthEventType.verificationCompleted:
final credential = event.data;
print('Verificacion completada. Credencial: $credential');
break;
case PhoneAuthEventType.verificationFailed:
final exception = event.data;
print('Verificacion fallida. Excepcion: $exception');
emit(AuthStateFailure(message: "Error inesperado. $exception"));
return;
case PhoneAuthEventType.codeAutoRetrievalTimeout:
final verificationId = event.data as String;
print('Tiempo de espera agotado. ID: $verificationId');
emit(const AuthStateFailure(
message: "Tiempo de espera agotado.",
));
break;
case PhoneAuthEventType.codeSent:
final eventData = event.data as Map<String, dynamic>;
final verificationId = eventData['verificationId'] as String;
final resendToken = eventData['resendToken'] as int?;
print('Codigo enviado. ID: $verificationId, resendToken: $resendToken');
_verificationId = verificationId;
emit(const AuthStateVerifyOAuth(false));
break;
}
}
await _userRepository.signInWithPhoneNumber(event.phoneNumber);
emit(const AuthStateVerifyOAuth(false));
} catch (e) {
emit(const AuthStateFailure(message: "Error inesperado."));
emit(AuthStateFailure(message: "Error al enviar código. $e"));
}
}
@@ -144,8 +113,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
emit(AuthStateProcess());
try {
final bool isVerified = await _userRepository.linkWithOTP(
event.phoneNumber, _verificationId ?? '', event.code);
event.phoneNumber, '', event.code);
if (isVerified) {
emit(AuthStateSuccess());
} else {