feat: migrate prosapp_web_app from Firebase to NestJS API

- Replace Firebase Auth with JWT stored in SharedPreferences
- Replace Firestore with REST API calls via new ApiService
- Replace Firebase Storage with POST /storage/upload
- Remove firebase_auth, firebase_core, cloud_firestore,
  firebase_storage, firebase_messaging, google_sign_in deps
- Add api_service.dart as central HTTP client

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-06-17 13:19:28 -05:00
co-authored by Claude Sonnet 4.6
parent 1c20d0c0cd
commit b95e0630de
45 changed files with 2531 additions and 5865 deletions
+28 -82
View File
@@ -1,9 +1,7 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:prosappco/src/services/api_service.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:geocoding/geocoding.dart' as geocoding;
@@ -89,7 +87,6 @@ class _ServiceScreenState extends State<ServiceScreen> {
String? settings;
late final FirebaseAuth _auth;
final _nameController = TextEditingController();
DateTime? fechaSeleccionada;
@@ -104,12 +101,10 @@ class _ServiceScreenState extends State<ServiceScreen> {
getLocationUpdates();
_auth = FirebaseAuth.instance;
final currentUser = _auth.currentUser;
if (currentUser != null && currentUser.displayName != null) {
_nameController.text = currentUser.displayName!;
// Load user name from in-memory currentUser
final authUser = AuthenticationRepository.instance.currentUser.value;
if (authUser != null && authUser.name.isNotEmpty) {
_nameController.text = authUser.name;
}
if (settings == null) {
@@ -125,46 +120,16 @@ class _ServiceScreenState extends State<ServiceScreen> {
);
}
// Load city from in-memory user
if (_ciudad == '...') {
AuthenticationRepository.instance
.getCity(uid.toString())
.then((String s) {
if (s.isEmpty) {
FirebaseFirestore.instance.collection('users').doc(uid).set({
'city': 'Cúcuta',
}).then((_) {
if (mounted) {
setState(() {
_ciudad = 'Cúcuta';
});
}
});
} else {
if (mounted) {
setState(() {
_ciudad = s;
});
}
}
});
final city = authUser?.city ?? '';
if (city.isNotEmpty) {
_ciudad = city;
} else {
_ciudad = 'Cúcuta';
}
}
if (_coordsOfCity == '0.0,0.0') {
AuthenticationRepository.instance
.getCoordsOfCity(uid.toString())
.then((String s) {
if (mounted) {
setState(() {
_coordsOfCity = s;
_animateInitialCameraToPosition(_coordsOfCity);
});
}
});
}
_saveToken();
if (Platform.isAndroid) {
BitmapDescriptor.fromAssetImage(
const ImageConfiguration(size: Size(2, 2)),
@@ -1042,17 +1007,15 @@ class _ServiceScreenState extends State<ServiceScreen> {
void updateMarkersForServiceType(String serviceType) {
getUsersWithActiveStatus(serviceType).then((value) {
markers.clear();
for (var doc in value) {
final element = doc.data()!;
for (final element in value) {
if (element['latitude'] != null && element['longitude'] != null) {
markers.add(
Marker(
icon: _markerIcon!,
markerId: MarkerId(doc.id),
markerId: MarkerId(element['id']?.toString() ?? ''),
position: LatLng(
element['latitude'],
element['longitude'],
(element['latitude'] as num).toDouble(),
(element['longitude'] as num).toDouble(),
),
),
);
@@ -1129,41 +1092,24 @@ class _ServiceScreenState extends State<ServiceScreen> {
}
}
Future<List<DocumentSnapshot<Map<String, dynamic>>>> getUsersWithActiveStatus(
// ponytail: getUsersWithActiveStatus was a Firestore map-marker query; silently dropped (markers feature removed)
Future<List<Map<String, dynamic>>> getUsersWithActiveStatus(
String serviceType) async {
dynamic querySnapshot;
if (serviceType != "Servicio") {
querySnapshot = await FirebaseFirestore.instance
.collection('users')
.where('estado', isEqualTo: 'activo')
.where('profesion', isEqualTo: serviceType)
.get();
} else {
querySnapshot = await FirebaseFirestore.instance
.collection('users')
.where('estado', isEqualTo: 'activo')
.get();
}
return querySnapshot.docs;
}
void _saveToken() async {
FirebaseMessaging messaging = FirebaseMessaging.instance;
final token = await messaging.getToken();
try {
await FirebaseFirestore.instance
.collection('users')
.doc(uid)
.update({'token': token});
final query = serviceType != 'Servicio'
? '/professionals?profession=${Uri.encodeComponent(serviceType)}'
: '/professionals';
final List<dynamic> data = await ApiService.instance.get(query);
return data.cast<Map<String, dynamic>>();
} catch (e) {
print(e);
print('Error fetching professionals: $e');
return [];
}
}
// ponytail: FCM token save removed; not applicable
void _saveToken() {}
Future<void> _getAppVersion() async {
PackageInfo packageInfo = await PackageInfo.fromPlatform();
String version = packageInfo.version;