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
@@ -3,4 +3,5 @@ library profession_repository;
export 'src/models/models.dart';
export 'src/entities/entities.dart';
export 'src/repositories/profession_repo.dart';
export 'src/repositories/firebase_profession_repository.dart';
export 'src/repositories/firebase_profession_repository.dart';
export 'src/repositories/api_profession_repository.dart';
@@ -0,0 +1,46 @@
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:profession_repository/profession_repository.dart';
import 'profession_repo.dart';
const _base = 'https://backend.prosapp.co/api/v1';
class ApiProfessionRepository implements ProfessionRepository {
Future<String?> _getToken() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString('token');
}
Future<Map<String, String>> _headers() async {
final t = await _getToken();
return {
'Content-Type': 'application/json',
if (t != null) 'Authorization': 'Bearer $t',
};
}
@override
Future<Professions> getProfessions() async {
try {
final res = await http.get(
Uri.parse('$_base/professions'),
headers: await _headers(),
);
final data = jsonDecode(res.body);
// Backend returns either a list of profession objects or a map with a professions key
if (data is List) {
final names = data
.map((e) => (e['name'] ?? e['title'] ?? e.toString()).toString())
.toList();
return Professions(names);
} else if (data is Map && data.containsKey('professions')) {
return Professions(List<String>.from(data['professions']));
}
return Professions([]);
} catch (e) {
rethrow;
}
}
}
+4 -2
View File
@@ -11,8 +11,10 @@ dependencies:
flutter:
sdk: flutter
equatable: ^2.0.5
http: ^1.1.0
shared_preferences: ^2.0.10
# Firebase
# Firebase kept for FirebaseProfessionRepository (legacy fallback)
cloud_firestore: ^4.15.4
firebase_core: ^2.25.4
@@ -23,4 +25,4 @@ dev_dependencies:
sdk: flutter
flutter:
uses-material-design: true
uses-material-design: true