feat: migrate prosappco from Firebase to NestJS REST API (Fase 2)

- Replace all Firebase* repositories with Api* repositories using HTTP + SharedPreferences JWT
- Remove Firebase.initializeApp() and firebase_messaging background handler from main.dart
- Update DI (app_di.dart) to inject Api* repositories instead of Firebase* ones
- Replace all Timestamp/cloud_firestore usage with ISO 8601 String dates
- Stub PhoneVerificationService (Firebase phone OTP → backend OTP when implemented)
- Add ApiService singleton with JWT management in lib/services/
- Legacy firebase_*_repository.dart files preserved for Fase 4 cleanup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-06-17 16:53:11 -05:00
co-authored by Claude Sonnet 4.6
parent 726cf12fd2
commit 733384091c
65 changed files with 1404 additions and 389 deletions
@@ -1,25 +1,16 @@
import 'dart:developer';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:prosappco/firebase_options.dart';
import 'package:prosappco/local_notifications/local_notifications.dart';
import 'package:user_repository/user_repository.dart';
part 'notification_event.dart';
part 'notification_state.dart';
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
}
// Stub: Firebase messaging removed. Background handler is no longer needed.
Future<void> firebaseMessagingBackgroundHandler(dynamic message) async {}
class NotificationBloc extends Bloc<NotificationEvent, NotificationState> {
FirebaseMessaging messaging = FirebaseMessaging.instance;
final Future<void> Function() requestLocalNotificationPermission;
final void Function({
required int id,
@@ -33,83 +24,18 @@ class NotificationBloc extends Bloc<NotificationEvent, NotificationState> {
required this.showLocalNotification})
: super(const NotificationState()) {
on<NotificationStatusChanged>(_notificationStatusChanged);
_initialStatusCheck();
_onForegroundMessage();
}
static Future<void> initializeFCM() async {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
}
void _notificationStatusChanged(
NotificationStatusChanged event, Emitter<NotificationState> emit) {
emit(state.copyWith(status: event.status));
_getFCMToken();
}
void _initialStatusCheck() async {
final settings = await messaging.getNotificationSettings();
add(NotificationStatusChanged(settings.authorizationStatus));
_getFCMToken();
}
Future<void> _saveFCMTokenToFirestore(String token) async {
try {
CollectionReference users = FirebaseFirestore.instance.collection('users');
await users.doc(FirebaseAuth.instance.currentUser!.uid).update({
'token': token,
});
} catch (e) {
print('tokenFCM Error saving FCM token to Firestore: $e');
}
}
void _getFCMToken() async {
if (state.status != AuthorizationStatus.authorized) return;
final fcmToken = await messaging.getToken();
log('tokenFCM ${fcmToken.toString()}');
if (fcmToken == null) return;
_saveFCMTokenToFirestore(fcmToken);
}
void _handleRemoteMessage(RemoteMessage message) {
if (message.notification == null) return;
showLocalNotification(
id: 1,
title: message.notification!.title,
body: message.notification!.body,
);
}
void _onForegroundMessage() {
FirebaseMessaging.onMessage.listen(_handleRemoteMessage);
}
void requestPermission() async {
NotificationSettings settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
// Solicitar permiso a las local notificaciones
await requestLocalNotificationPermission();
add(NotificationStatusChanged(settings.authorizationStatus));
try {
await requestLocalNotificationPermission();
} catch (e) {
log('NotificationBloc.requestPermission error: $e');
}
}
}
@@ -1,5 +1,13 @@
part of 'notification_bloc.dart';
// Stub for firebase_messaging AuthorizationStatus
enum AuthorizationStatus {
authorized,
denied,
notDetermined,
provisional,
}
class NotificationState extends Equatable {
final AuthorizationStatus status;