diff --git a/.env b/.env index 10147d1..13fc12a 100644 --- a/.env +++ b/.env @@ -1,7 +1 @@ -API_KEY=AIzaSyCNpUV_4cMEL9QZx7NESXK7QAlRjRGwx_Y -AUTH_DOMAIN=prosapp-5747a.firebaseapp.com -PROJECT_ID=prosapp-5747a -STORAGE_BUCKET=prosapp-5747a.appspot.com -MESSAGING_SENDER_ID=245204384533 -APP_ID=1:245204384533:web:1b8f0b4c1d9ae21d9f871c -MEASUREMENT_ID=G-EVBEQRZEDY +API_BASE_URL=https://backend.prosapp.co/api/v1 diff --git a/lib/main.dart b/lib/main.dart index 629177f..237165a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,3 @@ -import 'package:firebase_core/firebase_core.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter/material.dart'; import 'package:intl/date_symbol_data_local.dart'; @@ -30,18 +29,6 @@ void main() async { await dotenv.load(fileName: ".env"); - await Firebase.initializeApp( - options: FirebaseOptions( - apiKey: dotenv.env['API_KEY']!, - authDomain: dotenv.env['AUTH_DOMAIN'], - projectId: dotenv.env['PROJECT_ID']!, - storageBucket: dotenv.env['STORAGE_BUCKET'], - messagingSenderId: dotenv.env['MESSAGING_SENDER_ID']!, - appId: dotenv.env['APP_ID']!, - measurementId: dotenv.env['MEASUREMENT_ID'], - ), - ); - await LocalStorage.configurePrefs(); await initializeDateFormatting('es_ES', null); diff --git a/lib/models/comment_entity.dart b/lib/models/comment_entity.dart index a9ea835..6223fbf 100644 --- a/lib/models/comment_entity.dart +++ b/lib/models/comment_entity.dart @@ -1,5 +1,3 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; - class CommentEntity { final String authorId; final String destinationId; @@ -7,7 +5,7 @@ class CommentEntity { final String content; final double score; final bool isFromUser; - final Timestamp createdAt; + final String createdAt; const CommentEntity({ required this.authorId, @@ -21,13 +19,13 @@ class CommentEntity { static CommentEntity fromDocument(Map doc) { return CommentEntity( - authorId: doc['author_id'] as String, - destinationId: doc['destination_id'] as String, - serviceId: doc['service_id'] as String, - content: doc['content'] as String, - score: doc['score'] as double, - isFromUser: doc['is_from_user'] as bool, - createdAt: doc['created_at'] as Timestamp, + authorId: doc['author_id'] as String? ?? '', + destinationId: doc['destination_id'] as String? ?? '', + serviceId: doc['service_id'] as String? ?? '', + content: doc['content'] as String? ?? '', + score: (doc['score'] as num?)?.toDouble() ?? 0.0, + isFromUser: doc['is_from_user'] as bool? ?? false, + createdAt: doc['created_at']?.toString() ?? '', ); } @@ -45,14 +43,6 @@ class CommentEntity { @override String toString() { - return '''CommentEntity{ - authorId: $authorId, - destinationId: $destinationId, - serviceId: $serviceId, - content: $content, - score: $score, - isFromUser: $isFromUser, - createdAt: $createdAt - }'''; + return 'CommentEntity{authorId: $authorId, destinationId: $destinationId, score: $score}'; } } diff --git a/lib/models/service.dart b/lib/models/service.dart index 0614a0d..e945695 100644 --- a/lib/models/service.dart +++ b/lib/models/service.dart @@ -1,4 +1,3 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; import 'package:prosapp_web_app/models/service_location_preferences.dart'; import 'package:prosapp_web_app/models/service_status.dart'; @@ -14,7 +13,7 @@ class Service { final double latitude; final double longitude; final String day; - final Timestamp createdAt; + final String createdAt; final String description; final TimeOfDay range1Hour1; final TimeOfDay range1Hour2; @@ -46,28 +45,24 @@ class Service { return Service( id: id, professionalId: doc['professional_id'] as String, - professionalScored: doc['professional_scored'] as bool, + professionalScored: doc['professional_scored'] as bool? ?? false, userId: doc['user_id'] as String, - userScored: doc['user_scored'] as bool, - address: doc['address'] as String, - aditionalAddress: doc['aditional_address'] as String, - latitude: doc['latitude'] as double, - longitude: doc['longitude'] as double, - day: doc['day'] as String, - createdAt: doc['created_at'] as Timestamp, - description: doc['description'] as String, - range1Hour1: parseTimeOfDay(doc['range1_hour1'] as String), - range1Hour2: parseTimeOfDay(doc['range1_hour2'] as String), - status: intToEnumService(doc['status'] as int), - rate: doc['rate'] as String, - location: intToEnum(doc['location'] as int), + userScored: doc['user_scored'] as bool? ?? false, + address: doc['address'] as String? ?? '', + aditionalAddress: doc['aditional_address'] as String? ?? '', + latitude: (doc['latitude'] as num?)?.toDouble() ?? 0.0, + longitude: (doc['longitude'] as num?)?.toDouble() ?? 0.0, + day: doc['day'] as String? ?? '', + createdAt: doc['created_at']?.toString() ?? '', + description: doc['description'] as String? ?? '', + range1Hour1: parseTimeOfDay(doc['range1_hour1'] as String? ?? '0:0'), + range1Hour2: parseTimeOfDay(doc['range1_hour2'] as String? ?? '0:0'), + status: intToEnumService((doc['status'] as num?)?.toInt() ?? 0), + rate: doc['rate'] as String? ?? '', + location: intToEnum((doc['location'] as num?)?.toInt() ?? 0), ); } - static Service fromDocument(DocumentSnapshot> doc) { - return fromJson(doc.data()!, doc.id); - } - Map toDocument() { return { 'id': id, @@ -96,21 +91,12 @@ class Service { } String? formatTimeOfDay(TimeOfDay? time) { - if (time != null) { - return "${time.hour.toString()}:${time.minute.toString()}"; - } + if (time != null) return '${time.hour}:${time.minute}'; return null; } @override String toString() { - return '''Service { - professionalId: $professionalId, - userId: $userId, - day: $day, - createdAt: $createdAt, - status: $status, - location: $location - }'''; + return 'Service{professionalId: $professionalId, userId: $userId, day: $day, status: $status}'; } } diff --git a/lib/models/usuario_profesional.dart b/lib/models/usuario_profesional.dart index 1e61f76..1fac9fa 100644 --- a/lib/models/usuario_profesional.dart +++ b/lib/models/usuario_profesional.dart @@ -21,12 +21,19 @@ class UsuarioProfesional { }; } - // Método para deserializar desde JSON factory UsuarioProfesional.fromJson(Map json) { return UsuarioProfesional( user: Usuario.fromDocument(json['user']), professionalInfo: Profesional.fromDocument(json['professionalInfo']), - averageScore: json['averageScore'].toDouble(), + averageScore: (json['averageScore'] as num?)?.toDouble() ?? 0.0, + ); + } + + static UsuarioProfesional fromDocument(Map doc) { + return UsuarioProfesional( + user: Usuario.fromDocument(doc['user'] as Map), + professionalInfo: Profesional.fromDocument(doc['professional_info'] as Map), + averageScore: (doc['average_score'] as num?)?.toDouble() ?? 0.0, ); } diff --git a/lib/providers/auth_provider.dart b/lib/providers/auth_provider.dart index 9c22f8a..90544f6 100644 --- a/lib/providers/auth_provider.dart +++ b/lib/providers/auth_provider.dart @@ -1,13 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:prosapp_web_app/models/comment_entity.dart'; -import 'package:prosapp_web_app/models/profesional.dart'; - import 'package:prosapp_web_app/models/usuario.dart'; import 'package:prosapp_web_app/providers/professional_provider.dart'; import 'package:prosapp_web_app/providers/services_provider.dart'; import 'package:prosapp_web_app/router/router.dart'; +import 'package:prosapp_web_app/services/api_service.dart'; import 'package:prosapp_web_app/services/navigation_service.dart'; import 'package:prosapp_web_app/services/notifications_service.dart'; import 'package:provider/provider.dart'; @@ -16,14 +12,10 @@ enum AuthStatus { checking, authenticated, notAuthenticated } class AuthProvider extends ChangeNotifier { Usuario? user; - Profesional? professional; double userAverageScore = 0.0; - AuthStatus authStatus = AuthStatus.checking; - final FirebaseAuth _firebaseAuth = FirebaseAuth.instance; - final FirebaseFirestore _firestore = FirebaseFirestore.instance; - String? _verificationId; + final _api = ApiService.instance; AuthProvider() { isAuthenticated(); @@ -31,81 +23,59 @@ class AuthProvider extends ChangeNotifier { Future login(String email, String password) async { try { - await _firebaseAuth.signInWithEmailAndPassword( - email: email, password: password); - - final userData = await _firestore - .collection('users') - .doc(_firebaseAuth.currentUser!.uid) - .get(); - user = Usuario.fromDocument(userData.data()!); - + final data = await _api.post('/auth/login', {'email': email, 'password': password}); + await _api.saveToken(data['token'] as String); + user = Usuario.fromDocument(data['user'] as Map); + userAverageScore = await _loadAverageScore(user!.id); authStatus = AuthStatus.authenticated; - notifyListeners(); - NavigationService.replaceTo(Flurorouter.dashboardRoute); } catch (e) { authStatus = AuthStatus.notAuthenticated; notifyListeners(); - - NotificationsService.showSnackBarError( - 'Usuario o contraseña incorrectos'); + NotificationsService.showSnackBarError('Usuario o contraseña incorrectos'); } } - Future verifyPhoneNumberForLink(String phoneNumber) async { + Future register(String email, String password, String name) async { try { - await _firebaseAuth.verifyPhoneNumber( - phoneNumber: phoneNumber, - timeout: const Duration(seconds: 60), - verificationCompleted: (PhoneAuthCredential credential) async { - if (_firebaseAuth.currentUser != null) { - // Vincula el número de teléfono a la cuenta actual - await _firebaseAuth.currentUser!.linkWithCredential(credential); - NotificationsService.showSnackbar('Número vinculado exitosamente'); - authStatus = AuthStatus.authenticated; - notifyListeners(); - } - }, - verificationFailed: (FirebaseAuthException e) { - NotificationsService.showSnackBarError( - 'Error en la verificación del teléfono: ${e.message}'); - }, - codeSent: (String verificationId, int? resendToken) { - _verificationId = verificationId; - notifyListeners(); - }, - codeAutoRetrievalTimeout: (String verificationId) { - _verificationId = verificationId; - }, - ); + final data = await _api.post('/auth/register', { + 'email': email, + 'password': password, + 'name': name.trim(), + }); + await _api.saveToken(data['token'] as String); + user = Usuario.fromDocument(data['user'] as Map); + authStatus = AuthStatus.authenticated; + notifyListeners(); + NavigationService.replaceTo(Flurorouter.dashboardRoute); + } catch (e) { + authStatus = AuthStatus.notAuthenticated; + notifyListeners(); + NotificationsService.showSnackBarError('Email ya registrado'); + } + } + + Future verifyPhoneNumber(String phoneNumber) async { + try { + await _api.post('/auth/phone/send', {'phone': phoneNumber}); + notifyListeners(); } catch (e) { NotificationsService.showSnackBarError('Error al enviar OTP'); } } - Future linkPhoneWithOTP(String smsCode) async { + Future signInWithOTP(String phoneNumber, String smsCode) async { try { - final credential = PhoneAuthProvider.credential( - verificationId: _verificationId!, - smsCode: smsCode, - ); - - if (_firebaseAuth.currentUser != null) { - await _firebaseAuth.currentUser!.linkWithCredential(credential); - - await FirebaseFirestore.instance - .collection('users') - .doc(_firebaseAuth.currentUser!.uid) - .update({'phone': _firebaseAuth.currentUser!.phoneNumber}); - - NotificationsService.showSnackbar('Número vinculado exitosamente'); - - authStatus = AuthStatus.authenticated; - notifyListeners(); - NavigationService.replaceTo(Flurorouter.profileRoute); - } + final data = await _api.post('/auth/phone/verify', { + 'phone': phoneNumber, + 'code': smsCode, + }); + await _api.saveToken(data['token'] as String); + user = Usuario.fromDocument(data['user'] as Map); + authStatus = AuthStatus.authenticated; + notifyListeners(); + NavigationService.replaceTo(Flurorouter.dashboardRoute); } catch (e) { authStatus = AuthStatus.notAuthenticated; notifyListeners(); @@ -113,63 +83,59 @@ class AuthProvider extends ChangeNotifier { } } - Future register(String email, String password, String name) async { + Future verifyPhoneNumberForLink(String phoneNumber) async { try { - UserCredential userCredential = - await _firebaseAuth.createUserWithEmailAndPassword( - email: email, - password: password, - ); - - User? user = userCredential.user; - if (user != null) { - await _firestore.collection('users').doc(user.uid).set({ - 'birthday': "", - 'city': "", - 'email': user.email, - 'gender': "", - 'id': user.uid, - 'name': name.trim(), - 'nickname': name.trim().toLowerCase(), - 'phone': "", - 'picture': "", - 'professional_state': 0, - 'token': "", - }); - - authStatus = AuthStatus.authenticated; - notifyListeners(); - - NavigationService.replaceTo(Flurorouter.dashboardRoute); - } - } catch (e) { - authStatus = AuthStatus.notAuthenticated; + await _api.post('/auth/phone/link/send', {'phone': phoneNumber}); notifyListeners(); + } catch (e) { + NotificationsService.showSnackBarError('Error al enviar OTP'); + } + } - NotificationsService.showSnackBarError('Email ya registrado'); + Future linkPhoneWithOTP(String phoneNumber, String smsCode) async { + try { + await _api.post('/auth/phone/link/verify', { + 'phone': phoneNumber, + 'code': smsCode, + }); + user = await _fetchMe(); + NotificationsService.showSnackbar('Número vinculado exitosamente'); + authStatus = AuthStatus.authenticated; + notifyListeners(); + NavigationService.replaceTo(Flurorouter.profileRoute); + } catch (e) { + NotificationsService.showSnackBarError('Error en la verificación OTP'); + } + } + + Future addEmailAndPassword(String email, String password) async { + try { + await _api.patch('/users/me', {'email': email, 'password': password}); + user = await _fetchMe(); + notifyListeners(); + NotificationsService.showSnackbar('Email y contraseña añadidos exitosamente'); + NavigationService.replaceTo(Flurorouter.profileRoute); + } catch (e) { + NotificationsService.showSnackBarError('Error al añadir email'); } } Future isAuthenticated() async { - final User? firebaseUser = _firebaseAuth.currentUser; - - if (firebaseUser == null) { + final token = await _api.getToken(); + if (token == null) { authStatus = AuthStatus.notAuthenticated; notifyListeners(); return false; } - final userData = - await _firestore.collection('users').doc(firebaseUser.uid).get(); - - if (userData.exists) { - user = Usuario.fromDocument(userData.data()!); - - userAverageScore = await _getUserAverageScore(user!.id); - + try { + final data = await _api.get('/auth/me'); + user = Usuario.fromDocument(data as Map); + userAverageScore = await _loadAverageScore(user!.id); authStatus = AuthStatus.authenticated; notifyListeners(); return true; - } else { + } catch (e) { + await _api.deleteToken(); authStatus = AuthStatus.notAuthenticated; notifyListeners(); return false; @@ -177,158 +143,32 @@ class AuthProvider extends ChangeNotifier { } Future logout() async { - await _firebaseAuth.signOut(); + await _api.deleteToken(); authStatus = AuthStatus.notAuthenticated; + user = null; notifyListeners(); - Provider.of( - NavigationService.navigatorKey.currentContext!, - listen: false) - .logout(); - Provider.of( - NavigationService.navigatorKey.currentContext!, - listen: false) - .logout(); + final ctx = NavigationService.navigatorKey.currentContext!; + Provider.of(ctx, listen: false).logout(); + Provider.of(ctx, listen: false).logout(); NavigationService.replaceTo(Flurorouter.phoneLoginRoute); } - void refreshUser() { - isAuthenticated(); + void refreshUser() => isAuthenticated(); + + Future _fetchMe() async { + final data = await _api.get('/auth/me'); + return Usuario.fromDocument(data as Map); } - Future verifyPhoneNumber(String phoneNumber) async { + Future _loadAverageScore(String userId) async { try { - await _firebaseAuth.verifyPhoneNumber( - phoneNumber: phoneNumber, - timeout: const Duration(seconds: 60), - verificationCompleted: (PhoneAuthCredential credential) async { - await _firebaseAuth.signInWithCredential(credential); - authStatus = AuthStatus.authenticated; - notifyListeners(); - NavigationService.replaceTo(Flurorouter.dashboardRoute); - }, - verificationFailed: (FirebaseAuthException e) { - NotificationsService.showSnackBarError( - 'La verificación del teléfono falló: ${e.message}'); - }, - codeSent: (String verificationId, int? resendToken) { - _verificationId = verificationId; - notifyListeners(); - }, - codeAutoRetrievalTimeout: (String verificationId) { - _verificationId = verificationId; - }, - ); - } catch (e) { - NotificationsService.showSnackBarError('Error al enviar OTP'); - } - } - - Future signInWithOTP(String smsCode) async { - try { - final credential = PhoneAuthProvider.credential( - verificationId: _verificationId!, - smsCode: smsCode, - ); - await _firebaseAuth.signInWithCredential(credential); - - User? currentUser = _firebaseAuth.currentUser; - - if (currentUser != null) { - final userData = - await _firestore.collection('users').doc(currentUser.uid).get(); - - if (userData.exists) { - user = Usuario.fromDocument(userData.data()!); - } else { - await _firestore.collection('users').doc(currentUser.uid).set({ - 'birthday': "", - 'city': "", - 'email': "", - 'gender': "", - 'id': currentUser.uid, - 'name': "", - 'nickname': "", - 'phone': currentUser.phoneNumber, - 'picture': "", - 'professional_state': 0, - 'token': "", - }); - - final newUserData = - await _firestore.collection('users').doc(currentUser.uid).get(); - user = Usuario.fromDocument(newUserData.data()!); - } - - authStatus = AuthStatus.authenticated; - notifyListeners(); - - NavigationService.replaceTo(Flurorouter.dashboardRoute); - } - } catch (e) { - authStatus = AuthStatus.notAuthenticated; - notifyListeners(); - NotificationsService.showSnackBarError('Error en la verificación OTP'); - } - } - - Future addEmailAndPassword(String email, String password) async { - try { - final User? currentUser = _firebaseAuth.currentUser; - - if (currentUser != null) { - await currentUser.updateEmail(email); - - await currentUser.updatePassword(password); - - await _firestore.collection('users').doc(currentUser.uid).update({ - 'email': email, - }); - - notifyListeners(); - - NotificationsService.showSnackbar( - 'Email y contraseña añadidos exitosamente'); - - NavigationService.replaceTo(Flurorouter.profileRoute); - } - } catch (e) { - if (e is FirebaseAuthException && e.code == 'email-already-in-use') { - NotificationsService.showSnackBarError('El correo ya existe'); - } - - if (e is FirebaseAuthException && e.code == 'invalid-email') { - NotificationsService.showSnackBarError('El correo no es vßlido'); - } - - if (e is FirebaseAuthException && e.code == 'weak-password') { - NotificationsService.showSnackBarError( - 'La contraseña debe tener al menos 6 caracteres'); - } - - if (e is FirebaseAuthException && e.code == 'requires-recent-login') { - NotificationsService.showSnackBarError( - 'Debes iniciar sesión recientemente antes de agregar email y contraseña'); - } - } - } - - Future _getUserAverageScore(String userId) async { - final querySnapshot = await FirebaseFirestore.instance - .collection('comments') - .where('destination_id', isEqualTo: userId) - .where('is_from_user', isEqualTo: false) - .get(); - - if (querySnapshot.docs.isEmpty) { + final data = await _api.get('/comments/reputation/$userId'); + final rep = data as Map; + return (rep['average'] as num?)?.toDouble() ?? 0.0; + } catch (_) { return 0.0; } - - final scores = querySnapshot.docs - .map((e) => CommentEntity.fromDocument(e.data()).score) - .toList(); - final averageScore = scores.reduce((a, b) => a + b) / scores.length; - return averageScore; } } diff --git a/lib/providers/calendar_services_provider.dart b/lib/providers/calendar_services_provider.dart index 492e47b..ede51ab 100644 --- a/lib/providers/calendar_services_provider.dart +++ b/lib/providers/calendar_services_provider.dart @@ -1,16 +1,14 @@ import 'package:flutter/material.dart'; -import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:prosapp_web_app/models/service.dart'; import 'package:prosapp_web_app/models/servicio_profesional.dart'; import 'package:prosapp_web_app/models/usuario.dart'; +import 'package:prosapp_web_app/services/api_service.dart'; class CalendarServicesProvider extends ChangeNotifier { List services = []; ServicioProfesional? service; bool isLoading = true; - - final _servicesCollection = FirebaseFirestore.instance.collection('services'); - final _usersCollection = FirebaseFirestore.instance.collection('users'); + final _api = ApiService.instance; void logout() { services = []; @@ -22,47 +20,29 @@ class CalendarServicesProvider extends ChangeNotifier { getServicesForProfessional(String userId) async { try { isLoading = true; + final data = await _api.get('/services?professional_id=$userId&status=1,3') as List; + final servicios = data.map((e) { + final m = e as Map; + return Service.fromJson(m, m['id'] as String); + }).toList(); - final queryServices = await _servicesCollection - .where('professional_id', isEqualTo: userId) - .where('status', whereIn: [1, 3]).get(); + final ids = servicios.map((s) => s.userId).toSet().toList(); + final users = await Future.wait(ids.map((id) async { + final u = await _api.get('/users/$id'); + return Usuario.fromDocument(u as Map); + })); + final usersMap = {for (var u in users) u.id: u}; - final servicios = queryServices.docs.map(Service.fromDocument).toList(); - - final userIds = servicios.map((service) => service.userId).toList(); - - final queryUsers = await _usersCollection - .where(FieldPath.documentId, whereIn: userIds) - .get(); - - final users = - queryUsers.docs.map((e) => Usuario.fromDocument(e.data())).toList(); - - final usersMap = {for (var doc in users) doc.id: doc}; - - final servicesMap = (servicios.map((service) { - final user = usersMap[service.userId]; - - return ServicioProfesional( - user: user!, - service: service, - ); - }).toList()); - - services = servicesMap + services = servicios + .map((s) => ServicioProfesional(user: usersMap[s.userId]!, service: s)) + .toList() ..sort((a, b) { final dateA = DateTime.parse(a.service.day); final dateB = DateTime.parse(b.service.day); - final range1A = - a.service.range1Hour1.hour * 60 + a.service.range1Hour1.minute; - final range1B = - b.service.range1Hour1.hour * 60 + b.service.range1Hour1.minute; - - if (dateA.compareTo(dateB) != 0) { - return dateA.compareTo(dateB); - } else { - return range1A.compareTo(range1B); - } + if (dateA != dateB) return dateA.compareTo(dateB); + final tA = a.service.range1Hour1.hour * 60 + a.service.range1Hour1.minute; + final tB = b.service.range1Hour1.hour * 60 + b.service.range1Hour1.minute; + return tA.compareTo(tB); }); } catch (e) { print('Error obteniendo servicios: $e'); diff --git a/lib/providers/cities_provider.dart b/lib/providers/cities_provider.dart index 2a00477..81026d1 100644 --- a/lib/providers/cities_provider.dart +++ b/lib/providers/cities_provider.dart @@ -1,49 +1,35 @@ import 'package:flutter/material.dart'; -import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:prosapp_web_app/models/city.dart'; -import 'package:prosapp_web_app/models/country_entity.dart'; +import 'package:prosapp_web_app/services/api_service.dart'; class CitiesProvider extends ChangeNotifier { List cities = []; bool isLoading = true; - - final _citiesCollection = - FirebaseFirestore.instance.collection('countries v2'); + final _api = ApiService.instance; CitiesProvider() { getCities(); } getCoordsOfCity(String cityName) { - if (cities.isEmpty) return null; - for (var city in cities) { - if (city.cityName == cityName) { - return city.coordsOfCity; - } + if (city.cityName == cityName) return city.coordsOfCity; } return null; } getCities() async { try { - final querySnapshot = await _citiesCollection.doc('Colombia').get(); - - final data = querySnapshot.data(); - - final country = CountryEntity.fromDocument(data as Map); - - for (var region in country.regions) { - for (var city in region.cities) { - cities.add(City( - cityName: city.name, - coordsOfCity: city.coords, - stateOfCity: region.name, - countryOfCity: country.name, - )); - } - } - + final data = await _api.get('/cities') as List; + cities = data.map((e) { + final m = e as Map; + return City( + cityName: m['name'] as String, + coordsOfCity: m['coords'] as String? ?? '', + stateOfCity: m['state'] as String? ?? '', + countryOfCity: m['country'] as String? ?? 'Colombia', + ); + }).toList(); cities.sort((a, b) => a.cityName.compareTo(b.cityName)); } catch (e) { print('Error obteniendo ciudades: $e'); diff --git a/lib/providers/professional_detail_provider.dart b/lib/providers/professional_detail_provider.dart index 9d74006..5248c4d 100644 --- a/lib/providers/professional_detail_provider.dart +++ b/lib/providers/professional_detail_provider.dart @@ -1,43 +1,27 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; -import 'package:prosapp_web_app/models/comment_entity.dart'; import 'package:prosapp_web_app/models/profesional.dart'; import 'package:prosapp_web_app/models/usuario.dart'; import 'package:prosapp_web_app/models/usuario_profesional.dart'; +import 'package:prosapp_web_app/services/api_service.dart'; class ProfessionalDetailProvider extends ChangeNotifier { UsuarioProfesional? professional; bool isLoading = true; + final _api = ApiService.instance; Future getProfessionalById(String uid) async { try { isLoading = true; notifyListeners(); - final userDoc = - await FirebaseFirestore.instance.collection('users').doc(uid).get(); + final userData = await _api.get('/users/$uid'); + final user = Usuario.fromDocument(userData as Map); - if (!userDoc.exists) { - print('Profesional no encontrado.'); - return; - } + final proData = await _api.get('/professional-info/$uid'); + final professionalInfo = Profesional.fromDocument(proData as Map); - final user = Usuario.fromDocument(userDoc.data()!); - - final professionalDoc = await FirebaseFirestore.instance - .collection('professional_info') - .doc(uid) - .get(); - - if (!professionalDoc.exists) { - print('Información profesional no encontrada.'); - return; - } - - final professionalInfo = - Profesional.fromDocument(professionalDoc.data()!); - - final averageScore = await _getAverageScore(uid); + final repData = await _api.get('/comments/reputation/$uid'); + final averageScore = (repData['average'] as num?)?.toDouble() ?? 0.0; professional = UsuarioProfesional( user: user, @@ -51,22 +35,4 @@ class ProfessionalDetailProvider extends ChangeNotifier { notifyListeners(); } } - - Future _getAverageScore(String userId) async { - final querySnapshot = await FirebaseFirestore.instance - .collection('comments') - .where('destination_id', isEqualTo: userId) - .where('is_from_user', isEqualTo: true) - .get(); - - if (querySnapshot.docs.isEmpty) { - return 0.0; - } - - final scores = querySnapshot.docs - .map((e) => CommentEntity.fromDocument(e.data()).score) - .toList(); - final averageScore = scores.reduce((a, b) => a + b) / scores.length; - return averageScore; - } } diff --git a/lib/providers/professional_form_provider.dart b/lib/providers/professional_form_provider.dart index d292652..a38347f 100644 --- a/lib/providers/professional_form_provider.dart +++ b/lib/providers/professional_form_provider.dart @@ -1,18 +1,17 @@ import 'dart:typed_data'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:firebase_storage/firebase_storage.dart'; import 'package:flutter/material.dart'; import 'package:prosapp_web_app/models/location_preferences.dart'; import 'package:prosapp_web_app/models/payment_method_entity.dart'; import 'package:prosapp_web_app/models/profesional.dart'; import 'package:prosapp_web_app/models/schedules.dart'; +import 'package:prosapp_web_app/services/api_service.dart'; import 'package:prosapp_web_app/services/notifications_service.dart'; class ProfessionalFormProvider with ChangeNotifier { Profesional? profesional; GlobalKey formKey = GlobalKey(); GlobalKey profileFormKey = GlobalKey(); + final _api = ApiService.instance; copyProfesionalWith({ String? id, @@ -41,160 +40,70 @@ class ProfessionalFormProvider with ChangeNotifier { profession: profession ?? profesional!.profession, ratePreferences: ratePreferences, rate: rate ?? profesional!.rate, - locationPreferences: - locationPreferences ?? profesional!.locationPreferences, + locationPreferences: locationPreferences ?? profesional!.locationPreferences, bannerPicture: bannerPicture ?? profesional!.bannerPicture, - identificationPicture: - identificationPicture ?? profesional!.identificationPicture, + identificationPicture: identificationPicture ?? profesional!.identificationPicture, certificatePicture: certificatePicture ?? profesional!.certificatePicture, latitude: latitude ?? profesional!.latitude, longitude: longitude ?? profesional!.longitude, specializations: specializations ?? profesional!.specializations, - specializationsPictures: - specializationsPictures ?? profesional!.specializationsPictures, + specializationsPictures: specializationsPictures ?? profesional!.specializationsPictures, schedules: schedules ?? profesional!.schedules, paymentMethods: paymentMethods ?? profesional!.paymentMethods, ); - notifyListeners(); } - bool _validForm() { - return formKey.currentState!.validate(); - } + bool _validForm() => formKey.currentState!.validate(); + bool _validProfileForm() => profileFormKey.currentState!.validate(); - bool _validProfileForm() { - return profileFormKey.currentState!.validate(); - } - - setProfesional(Profesional profesional) { - this.profesional = profesional; + setProfesional(Profesional p) { + profesional = p; notifyListeners(); } Future updateProfesionalInfo(String userId) async { if (!_validForm()) return false; - - final docProfessional = FirebaseFirestore.instance - .collection('professional_info') - .doc(userId) - .withConverter( - fromFirestore: (snapshot, _) => - Profesional.fromDocument(snapshot.data()!), - toFirestore: (user, _) => user.toDocument(), - ); - - await docProfessional.set(profesional!); - + await _api.patch('/professional-info/$userId', profesional!.toDocument()); NotificationsService.showSnackbar('Información actualizada'); - return true; } Future updateProfesionalProfileInfo(String userId) async { if (!_validProfileForm()) return false; - - final docProfessional = FirebaseFirestore.instance - .collection('professional_info') - .doc(userId) - .withConverter( - fromFirestore: (snapshot, _) => - Profesional.fromDocument(snapshot.data()!), - toFirestore: (user, _) => user.toDocument(), - ); - - await docProfessional.set(profesional!); - + await _api.patch('/professional-info/$userId', profesional!.toDocument()); NotificationsService.showSnackbar('Información actualizada'); - return true; } Future updateProfesionalProfileScheduleInfo(String userId) async { - final docProfessional = FirebaseFirestore.instance - .collection('professional_info') - .doc(userId) - .withConverter( - fromFirestore: (snapshot, _) => - Profesional.fromDocument(snapshot.data()!), - toFirestore: (user, _) => user.toDocument(), - ); - - await docProfessional.set(profesional!); - + await _api.patch('/professional-info/$userId', profesional!.toDocument()); NotificationsService.showSnackbar('Información actualizada'); - return true; } - Future uploadPdfIdentification( - Uint8List fileBytes, String userId) async { - try { - final storageRef = FirebaseStorage.instance - .ref() - .child('$userId/PDF/${userId}_cedula.pdf'); - - await storageRef.putData(fileBytes); - final url = await storageRef.getDownloadURL(); - - copyProfesionalWith(identificationPicture: url); - - notifyListeners(); - - return profesional!; - } catch (e) { - print("Error al subir el PDF de identificación: $e"); - NotificationsService.showSnackbar('Error al subir el PDF'); - rethrow; - } + Future uploadPdfIdentification(Uint8List fileBytes, String userId) async { + final url = await _api.upload(fileBytes, '${userId}_cedula.pdf'); + if (url != null) copyProfesionalWith(identificationPicture: url); + notifyListeners(); + return profesional!; } - Future uploadPdfCertificate( - Uint8List fileBytes, String userId) async { - try { - final storageRef = FirebaseStorage.instance - .ref() - .child('$userId/PDF/${userId}_certificado.pdf'); - - await storageRef.putData(fileBytes); - final url = await storageRef.getDownloadURL(); - - copyProfesionalWith(certificatePicture: url); - - notifyListeners(); - - return profesional!; - } catch (e) { - print("Error al subir el PDF de identificación: $e"); - NotificationsService.showSnackbar('Error al subir el PDF'); - rethrow; - } + Future uploadPdfCertificate(Uint8List fileBytes, String userId) async { + final url = await _api.upload(fileBytes, '${userId}_certificado.pdf'); + if (url != null) copyProfesionalWith(certificatePicture: url); + notifyListeners(); + return profesional!; } - Future uploadPdfSpecializations( - List filesBytes, String userId) async { - try { - List urls = []; - - for (int i = 0; i < filesBytes.length; i++) { - final storageRef = FirebaseStorage.instance.ref().child( - '$userId/PDF/${userId}_${DateTime.now().millisecondsSinceEpoch}_especializacion_$i.pdf'); - - await storageRef.putData(filesBytes[i]); - - final url = await storageRef.getDownloadURL(); - urls.add(url); - } - - copyProfesionalWith(specializationsPictures: urls); - - notifyListeners(); - - return profesional!; - } catch (e) { - print("Error al subir los PDFs de especialización: $e"); - NotificationsService.showSnackbar('Error al subir los PDFs'); - rethrow; + Future uploadPdfSpecializations(List filesBytes, String userId) async { + List urls = []; + for (int i = 0; i < filesBytes.length; i++) { + final url = await _api.upload(filesBytes[i], '${userId}_especializacion_$i.pdf'); + if (url != null) urls.add(url); } + copyProfesionalWith(specializationsPictures: urls); + notifyListeners(); + return profesional!; } } diff --git a/lib/providers/professional_provider.dart b/lib/providers/professional_provider.dart index 7ff0fbd..8a6570c 100644 --- a/lib/providers/professional_provider.dart +++ b/lib/providers/professional_provider.dart @@ -1,32 +1,24 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/widgets.dart'; import 'package:prosapp_web_app/models/location_preferences.dart'; import 'package:prosapp_web_app/models/payment_method_entity.dart'; import 'package:prosapp_web_app/models/profesional.dart'; import 'package:prosapp_web_app/models/schedules.dart'; +import 'package:prosapp_web_app/services/api_service.dart'; class ProfessionalProvider extends ChangeNotifier { Profesional? profesional; bool _isProModeActive = false; + final _api = ApiService.instance; - final FirebaseAuth _firebaseAuth = FirebaseAuth.instance; - - bool get isProModeActive { - return _isProModeActive; - } + bool get isProModeActive => _isProModeActive; Future getProfessional(String uid) async { try { - final professional = await FirebaseFirestore.instance - .collection('professional_info') - .doc(uid) - .get(); - - profesional = Profesional.fromDocument(professional.data()!); + final data = await _api.get('/professional-info/$uid'); + profesional = Profesional.fromDocument(data as Map); } catch (e) { profesional = Profesional( - id: _firebaseAuth.currentUser!.uid, + id: uid, identification: '', address: '', aditionalAddress: '', @@ -45,12 +37,11 @@ class ProfessionalProvider extends ChangeNotifier { paymentMethods: PaymentMethodEntity.empty, ); } - notifyListeners(); return profesional!; } - logout() { + void logout() { _isProModeActive = false; notifyListeners(); } diff --git a/lib/providers/professionals_provider.dart b/lib/providers/professionals_provider.dart index fc01955..ebc2faa 100644 --- a/lib/providers/professionals_provider.dart +++ b/lib/providers/professionals_provider.dart @@ -1,14 +1,11 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; -import 'package:prosapp_web_app/models/comment_entity.dart'; -import 'package:prosapp_web_app/models/pro_state.dart'; -import 'package:prosapp_web_app/models/profesional.dart'; -import 'package:prosapp_web_app/models/usuario.dart'; import 'package:prosapp_web_app/models/usuario_profesional.dart'; +import 'package:prosapp_web_app/services/api_service.dart'; class ProfessionalsProvider extends ChangeNotifier { List professionals = []; bool isLoading = true; + final _api = ApiService.instance; ProfessionalsProvider() { getProfessionals(); @@ -16,42 +13,10 @@ class ProfessionalsProvider extends ChangeNotifier { getProfessionals() async { try { - final querySnapshot = await FirebaseFirestore.instance - .collection('users') - .where('professional_state', isEqualTo: ProState.active.index) - .get(); - - final users = querySnapshot.docs - .map((e) => Usuario.fromDocument(e.data())) + final data = await _api.get('/users/professionals'); + professionals = (data as List) + .map((e) => UsuarioProfesional.fromDocument(e as Map)) .toList(); - - final ids = users.map((e) => e.id).toList(); - - final querySnapshot2 = await FirebaseFirestore.instance - .collection('professional_info') - .where(FieldPath.documentId, whereIn: ids) - .get(); - - final professionalsInfo = querySnapshot2.docs - .map((e) => Profesional.fromDocument(e.data())) - .toList(); - - final professionalInfoMap = { - for (var doc in professionalsInfo) doc.id: doc - }; - - final usersMap = await Future.wait(users.map((user) async { - final professionalInfo = professionalInfoMap[user.id]; - final averageScore = await _getAverageScore(user.id); - return UsuarioProfesional( - user: user, - professionalInfo: professionalInfo!, - averageScore: averageScore, - ); - }).toList()); - - professionals = usersMap; - } catch (e) { print('Error obteniendo profesionales: $e'); } finally { @@ -59,22 +24,4 @@ class ProfessionalsProvider extends ChangeNotifier { notifyListeners(); } } - - Future _getAverageScore(String userId) async { - final querySnapshot = await FirebaseFirestore.instance - .collection('comments') - .where('destination_id', isEqualTo: userId) - .where('is_from_user', isEqualTo: true) - .get(); - - if (querySnapshot.docs.isEmpty) { - return 0.0; - } - - final scores = querySnapshot.docs - .map((e) => CommentEntity.fromDocument(e.data()).score) - .toList(); - final averageScore = scores.reduce((a, b) => a + b) / scores.length; - return averageScore; - } } diff --git a/lib/providers/professions_provider.dart b/lib/providers/professions_provider.dart index f592af7..41918f1 100644 --- a/lib/providers/professions_provider.dart +++ b/lib/providers/professions_provider.dart @@ -1,13 +1,11 @@ import 'package:flutter/material.dart'; -import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:prosapp_web_app/models/profession.dart'; +import 'package:prosapp_web_app/services/api_service.dart'; class ProfessionsProvider extends ChangeNotifier { List professions = []; bool isLoading = true; - - final _professionsCollection = - FirebaseFirestore.instance.collection('professions'); + final _api = ApiService.instance; ProfessionsProvider() { getProfessions(); @@ -15,14 +13,14 @@ class ProfessionsProvider extends ChangeNotifier { getProfessions() async { try { - final documentSnapshot = - await _professionsCollection.doc('professions').get(); - - final data = documentSnapshot.data() as Map; - - professions = (data['professions'] as List) - .map((item) => Profession(name: item as String)) - .toList(); + final data = await _api.get('/professions'); + if (data is List) { + professions = data.map((e) => Profession(name: e['name'] as String)).toList(); + } else if (data is Map && data['professions'] is List) { + professions = (data['professions'] as List) + .map((e) => Profession(name: e as String)) + .toList(); + } } catch (e) { print('Error obteniendo profesiones: $e'); } finally { diff --git a/lib/providers/profile_form_provider.dart b/lib/providers/profile_form_provider.dart index f26f937..90ef410 100644 --- a/lib/providers/profile_form_provider.dart +++ b/lib/providers/profile_form_provider.dart @@ -1,18 +1,14 @@ import 'dart:typed_data'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:firebase_storage/firebase_storage.dart'; import 'package:flutter/material.dart'; import 'package:prosapp_web_app/models/pro_state.dart'; import 'package:prosapp_web_app/models/usuario.dart'; +import 'package:prosapp_web_app/services/api_service.dart'; import 'package:prosapp_web_app/services/notifications_service.dart'; class ProfileFormProvider extends ChangeNotifier { Usuario? user; GlobalKey formKey = GlobalKey(); - - String? _verificationId; + final _api = ApiService.instance; void copyUserWith({ String? id, @@ -43,117 +39,45 @@ class ProfileFormProvider extends ChangeNotifier { notifyListeners(); } - bool _validForm() { - return formKey.currentState!.validate(); - } + bool _validForm() => formKey.currentState!.validate(); Future updateUserInfo() async { if (!_validForm()) return; - - final docUser = FirebaseFirestore.instance - .collection('users') - .doc(user!.id) - .withConverter( - fromFirestore: (snapshot, _) => - Usuario.fromDocument(snapshot.data()!), - toFirestore: (user, _) => user.toDocument(), - ); - - await docUser.set(user!); + await _api.patch('/users/me', user!.toDocument()); NotificationsService.showSnackbar('Información actualizada'); } Future updateUserInfoNoValid() async { - final docUser = FirebaseFirestore.instance - .collection('users') - .doc(user!.id) - .withConverter( - fromFirestore: (snapshot, _) => - Usuario.fromDocument(snapshot.data()!), - toFirestore: (user, _) => user.toDocument(), - ); - - await docUser.set(user!); + await _api.patch('/users/me', user!.toDocument()); NotificationsService.showSnackbar('Información actualizada'); } Future uploadPicture(Uint8List bytes) async { - try { - final storageRef = FirebaseStorage.instance - .ref() - .child('${user!.id}/PP/${user!.id}_lead'); - - await storageRef.putData(bytes); - - final url = await storageRef.getDownloadURL(); - - copyUserWith(picture: url); - notifyListeners(); - - return user!; - } catch (e) { - print("Error al subir la imagen: $e"); - rethrow; - } + final url = await _api.upload(bytes, 'profile_${user!.id}.jpg'); + if (url != null) copyUserWith(picture: url); + notifyListeners(); + return user!; } - // Agregar numero Future signUpWithPhoneNumber(String phoneNumber) async { try { - await FirebaseAuth.instance.verifyPhoneNumber( - phoneNumber: phoneNumber, - verificationCompleted: (PhoneAuthCredential credential) async { - await FirebaseAuth.instance.signInWithCredential(credential); - NotificationsService.showSnackbar('Autenticación exitosa'); - }, - verificationFailed: (FirebaseAuthException e) { - NotificationsService.showSnackbar( - 'Error en la verificación: ${e.message}'); - }, - codeSent: (String verificationId, int? resendToken) { - _verificationId = verificationId; - NotificationsService.showSnackbar( - 'Código enviado al número $phoneNumber'); - }, - codeAutoRetrievalTimeout: (String verificationId) { - _verificationId = verificationId; - }, - ); - - NotificationsService.showSnackbar('Código enviado'); + await _api.post('/auth/phone/link/send', {'phone': phoneNumber}); + NotificationsService.showSnackbar('Código enviado al número $phoneNumber'); } catch (e) { - NotificationsService.showSnackbar('Error al registrar con teléfono: $e'); + NotificationsService.showSnackbar('Error al enviar código: $e'); } } - Future linkPhoneNumberToExistingAccount( - String phoneNumber, String code) async { + Future linkPhoneNumberToExistingAccount(String phoneNumber, String code) async { try { - var phoneAuthCredential = PhoneAuthProvider.credential( - verificationId: _verificationId!, - smsCode: code, - ); - - User? user = FirebaseAuth.instance.currentUser; - - if (user != null) { - await user.linkWithCredential(phoneAuthCredential); - - copyUserWith(phone: phoneNumber); - notifyListeners(); - - NotificationsService.showSnackbar('Número vinculado exitosamente'); - return true; - } - return false; + await _api.post('/auth/phone/link/verify', {'phone': phoneNumber, 'code': code}); + copyUserWith(phone: phoneNumber); + notifyListeners(); + NotificationsService.showSnackbar('Número vinculado exitosamente'); + return true; } catch (e) { - if (e is FirebaseAuthException && e.code == 'invalid-verification-code') { - NotificationsService.showSnackbar('Código de verificación inválido'); - return false; - } else { - NotificationsService.showSnackbar('Error al vincular número: $e'); - rethrow; - } + NotificationsService.showSnackbar('Código de verificación inválido'); + return false; } } } diff --git a/lib/providers/services_provider.dart b/lib/providers/services_provider.dart index 8ce6097..d907f1e 100644 --- a/lib/providers/services_provider.dart +++ b/lib/providers/services_provider.dart @@ -1,18 +1,15 @@ import 'package:flutter/material.dart'; -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:prosapp_web_app/models/pro_state.dart'; import 'package:prosapp_web_app/models/service.dart'; import 'package:prosapp_web_app/models/service_status.dart'; import 'package:prosapp_web_app/models/servicio_profesional.dart'; import 'package:prosapp_web_app/models/usuario.dart'; +import 'package:prosapp_web_app/services/api_service.dart'; class ServicesProvider extends ChangeNotifier { List services = []; ServicioProfesional? service; bool isLoading = true; - - final _servicesCollection = FirebaseFirestore.instance.collection('services'); - final _usersCollection = FirebaseFirestore.instance.collection('users'); + final _api = ApiService.instance; void logout() { services = []; @@ -21,43 +18,30 @@ class ServicesProvider extends ChangeNotifier { notifyListeners(); } - Future changeServiceStatus( - String serviceId, ServiceStatus newStatus) async { + Future changeServiceStatus(String serviceId, ServiceStatus newStatus) async { try { - final statusValue = enumToIntService(newStatus); - await FirebaseFirestore.instance - .collection('services') - .doc(serviceId) - .update({'status': statusValue}); + await _api.patch('/services/$serviceId', {'status': enumToIntService(newStatus)}); notifyListeners(); } catch (e) { print('Error al actualizar el estado: $e'); } } - // cambiar el user_scored a true Future changeUserScored(String serviceId) async { try { - await FirebaseFirestore.instance - .collection('services') - .doc(serviceId) - .update({'user_scored': true}); + await _api.patch('/services/$serviceId', {'user_scored': true}); notifyListeners(); } catch (e) { - print('Error al actualizar el estado: $e'); + print('Error al actualizar user_scored: $e'); } } - // cambiar el professional_scored a true Future changeProfessionalScored(String serviceId) async { try { - await FirebaseFirestore.instance - .collection('services') - .doc(serviceId) - .update({'professional_scored': true}); + await _api.patch('/services/$serviceId', {'professional_scored': true}); notifyListeners(); } catch (e) { - print('Error al actualizar el estado: $e'); + print('Error al actualizar professional_scored: $e'); } } @@ -69,20 +53,12 @@ class ServicesProvider extends ChangeNotifier { getServiceForUser(String serviceId) async { try { isLoading = true; - - final queryService = await _servicesCollection.doc(serviceId).get(); - - final servicio = Service.fromDocument(queryService); - - final queryUsers = - await _usersCollection.doc(servicio.professionalId).get(); - - final user = Usuario.fromDocument(queryUsers.data()!); - - service = ServicioProfesional( - user: user, - service: servicio, - ); + final data = await _api.get('/services/$serviceId'); + final map = data as Map; + final servicio = Service.fromJson(map, map['id'] as String); + final userData = await _api.get('/users/${servicio.professionalId}'); + final user = Usuario.fromDocument(userData as Map); + service = ServicioProfesional(user: user, service: servicio); } catch (e) { service = null; } finally { @@ -94,19 +70,12 @@ class ServicesProvider extends ChangeNotifier { getServiceForProfessional(String serviceId) async { try { isLoading = true; - - final queryService = await _servicesCollection.doc(serviceId).get(); - - final servicio = Service.fromDocument(queryService); - - final queryUsers = await _usersCollection.doc(servicio.userId).get(); - - final user = Usuario.fromDocument(queryUsers.data()!); - - service = ServicioProfesional( - user: user, - service: servicio, - ); + final data = await _api.get('/services/$serviceId'); + final map = data as Map; + final servicio = Service.fromJson(map, map['id'] as String); + final userData = await _api.get('/users/${servicio.userId}'); + final user = Usuario.fromDocument(userData as Map); + service = ServicioProfesional(user: user, service: servicio); } catch (e) { service = null; } finally { @@ -115,270 +84,43 @@ class ServicesProvider extends ChangeNotifier { } } - getServicesForUser(String userId) async { + getServicesForUser(String userId) async => _loadServices('/services?user_id=$userId&status=0,1,3', forUser: true); + + getServicesRequestsForProfessional(String userId) async => _loadServices('/services?professional_id=$userId&status=0', forUser: false); + + getServicesForProfessional(String userId) async => _loadServices('/services?professional_id=$userId&status=1,3', forUser: false); + + getServicesHistoryForUser(String userId) async => _loadServices('/services?user_id=$userId&status=2,4,5', forUser: true); + + getServicesHistoryForProfessional(String userId) async => _loadServices('/services?professional_id=$userId&status=2,4,5', forUser: false); + + Future _loadServices(String path, {required bool forUser}) async { try { isLoading = true; + final data = await _api.get(path) as List; + final servicios = data.map((e) { + final m = e as Map; + return Service.fromJson(m, m['id'] as String); + }).toList(); - final queryServices = await _servicesCollection - .where('user_id', isEqualTo: userId) - .where('status', whereIn: [0, 1, 3]).get(); + final ids = servicios.map((s) => forUser ? s.professionalId : s.userId).toSet().toList(); + final users = await Future.wait(ids.map((id) async { + final u = await _api.get('/users/$id'); + return Usuario.fromDocument(u as Map); + })); + final usersMap = {for (var u in users) u.id: u}; - final servicios = queryServices.docs.map(Service.fromDocument).toList(); - - final professionalIds = - servicios.map((service) => service.professionalId).toList(); - - final queryUsers = await _usersCollection - .where('professional_state', isEqualTo: ProState.active.index) - .where(FieldPath.documentId, whereIn: professionalIds) - .get(); - - final professionalUsers = - queryUsers.docs.map((e) => Usuario.fromDocument(e.data())).toList(); - - final professionalUsersMap = { - for (var user in professionalUsers) user.id: user - }; - - final servicesMap = (servicios.map((service) { - final user = professionalUsersMap[service.professionalId]; - - return ServicioProfesional( - user: user!, - service: service, - ); - }).toList()); - - services = servicesMap + services = servicios.map((s) { + final userId = forUser ? s.professionalId : s.userId; + return ServicioProfesional(user: usersMap[userId]!, service: s); + }).toList() ..sort((a, b) { final dateA = DateTime.parse(a.service.day); final dateB = DateTime.parse(b.service.day); - final range1A = - a.service.range1Hour1.hour * 60 + a.service.range1Hour1.minute; - final range1B = - b.service.range1Hour1.hour * 60 + b.service.range1Hour1.minute; - - if (dateA.compareTo(dateB) != 0) { - return dateA.compareTo(dateB); - } else { - return range1A.compareTo(range1B); - } - }); - } catch (e) { - print('Error obteniendo servicios: $e'); - } finally { - isLoading = false; - notifyListeners(); - } - } - - getServicesRequestsForProfessional(String userId) async { - try { - isLoading = true; - - final queryServices = await _servicesCollection - .where('professional_id', isEqualTo: userId) - .where('status', whereIn: [0]).get(); - - final servicios = queryServices.docs.map(Service.fromDocument).toList(); - - final userIds = servicios.map((service) => service.userId).toList(); - - final queryUsers = await _usersCollection - .where(FieldPath.documentId, whereIn: userIds) - .get(); - - final users = - queryUsers.docs.map((e) => Usuario.fromDocument(e.data())).toList(); - - final usersMap = {for (var doc in users) doc.id: doc}; - - final servicesMap = (servicios.map((service) { - final user = usersMap[service.userId]; - - return ServicioProfesional( - user: user!, - service: service, - ); - }).toList()); - - services = servicesMap - ..sort((a, b) { - final dateA = DateTime.parse(a.service.day); - final dateB = DateTime.parse(b.service.day); - final range1A = - a.service.range1Hour1.hour * 60 + a.service.range1Hour1.minute; - final range1B = - b.service.range1Hour1.hour * 60 + b.service.range1Hour1.minute; - - if (dateA.compareTo(dateB) != 0) { - return dateA.compareTo(dateB); - } else { - return range1A.compareTo(range1B); - } - }); - } catch (e) { - print('Error obteniendo servicios: $e'); - } finally { - isLoading = false; - notifyListeners(); - } - } - - getServicesForProfessional(String userId) async { - try { - isLoading = true; - - final queryServices = await _servicesCollection - .where('professional_id', isEqualTo: userId) - .where('status', whereIn: [1, 3]).get(); - - final servicios = queryServices.docs.map(Service.fromDocument).toList(); - - final userIds = servicios.map((service) => service.userId).toList(); - - final queryUsers = await _usersCollection - .where(FieldPath.documentId, whereIn: userIds) - .get(); - - final users = - queryUsers.docs.map((e) => Usuario.fromDocument(e.data())).toList(); - - final usersMap = {for (var doc in users) doc.id: doc}; - - final servicesMap = (servicios.map((service) { - final user = usersMap[service.userId]; - - return ServicioProfesional( - user: user!, - service: service, - ); - }).toList()); - - services = servicesMap - ..sort((a, b) { - final dateA = DateTime.parse(a.service.day); - final dateB = DateTime.parse(b.service.day); - final range1A = - a.service.range1Hour1.hour * 60 + a.service.range1Hour1.minute; - final range1B = - b.service.range1Hour1.hour * 60 + b.service.range1Hour1.minute; - - if (dateA.compareTo(dateB) != 0) { - return dateA.compareTo(dateB); - } else { - return range1A.compareTo(range1B); - } - }); - } catch (e) { - print('Error obteniendo servicios: $e'); - } finally { - isLoading = false; - notifyListeners(); - } - } - - getServicesHistoryForUser(String userId) async { - try { - isLoading = true; - - final queryServices = await _servicesCollection - .where('user_id', isEqualTo: userId) - .where('status', whereIn: [2, 4, 5]).get(); - - final servicios = queryServices.docs.map(Service.fromDocument).toList(); - - final professionalIds = - servicios.map((service) => service.professionalId).toList(); - - final queryUsers = await _usersCollection - .where('professional_state', isEqualTo: ProState.active.index) - .where(FieldPath.documentId, whereIn: professionalIds) - .get(); - - final professionalUsers = - queryUsers.docs.map((e) => Usuario.fromDocument(e.data())).toList(); - - final professionalUsersMap = { - for (var user in professionalUsers) user.id: user - }; - - final servicesMap = (servicios.map((service) { - final user = professionalUsersMap[service.professionalId]; - - return ServicioProfesional( - user: user!, - service: service, - ); - }).toList()); - - services = servicesMap - ..sort((a, b) { - final dateA = DateTime.parse(a.service.day); - final dateB = DateTime.parse(b.service.day); - final range1A = - a.service.range1Hour1.hour * 60 + a.service.range1Hour1.minute; - final range1B = - b.service.range1Hour1.hour * 60 + b.service.range1Hour1.minute; - - if (dateA.compareTo(dateB) != 0) { - return dateA.compareTo(dateB); - } else { - return range1A.compareTo(range1B); - } - }); - } catch (e) { - print('Error obteniendo servicios: $e'); - } finally { - isLoading = false; - notifyListeners(); - } - } - - getServicesHistoryForProfessional(String userId) async { - try { - isLoading = true; - - final queryServices = await _servicesCollection - .where('professional_id', isEqualTo: userId) - .where('status', whereIn: [2, 4, 5]).get(); - - final servicios = queryServices.docs.map(Service.fromDocument).toList(); - - final userIds = servicios.map((service) => service.userId).toList(); - - final queryUsers = await _usersCollection - .where(FieldPath.documentId, whereIn: userIds) - .get(); - - final users = - queryUsers.docs.map((e) => Usuario.fromDocument(e.data())).toList(); - - final usersMap = {for (var doc in users) doc.id: doc}; - - final servicesMap = (servicios.map((service) { - final user = usersMap[service.userId]; - - return ServicioProfesional( - user: user!, - service: service, - ); - }).toList()); - - services = servicesMap - ..sort((a, b) { - final dateA = DateTime.parse(a.service.day); - final dateB = DateTime.parse(b.service.day); - final range1A = - a.service.range1Hour1.hour * 60 + a.service.range1Hour1.minute; - final range1B = - b.service.range1Hour1.hour * 60 + b.service.range1Hour1.minute; - - if (dateA.compareTo(dateB) != 0) { - return dateA.compareTo(dateB); - } else { - return range1A.compareTo(range1B); - } + if (dateA != dateB) return dateA.compareTo(dateB); + final tA = a.service.range1Hour1.hour * 60 + a.service.range1Hour1.minute; + final tB = b.service.range1Hour1.hour * 60 + b.service.range1Hour1.minute; + return tA.compareTo(tB); }); } catch (e) { print('Error obteniendo servicios: $e'); diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index dca64a9..ecd352e 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -1,12 +1,11 @@ import 'package:flutter/material.dart'; -import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:prosapp_web_app/models/setting.dart'; +import 'package:prosapp_web_app/services/api_service.dart'; class SettingsProvider extends ChangeNotifier { Setting? settings; bool isLoading = true; - - final _settingsCollection = FirebaseFirestore.instance.collection('settings'); + final _api = ApiService.instance; SettingsProvider() { getSettings(); @@ -14,8 +13,8 @@ class SettingsProvider extends ChangeNotifier { getSettings() async { try { - final querySnapshot = await _settingsCollection.doc('global').get(); - settings = Setting.fromDocument(querySnapshot.data()!); + final data = await _api.get('/settings'); + settings = Setting.fromDocument(data as Map); } catch (e) { print('Error obteniendo los settings: $e'); } finally { diff --git a/lib/repositories/firebase_chat_repository.dart b/lib/repositories/firebase_chat_repository.dart index 662d069..8ce15f5 100644 --- a/lib/repositories/firebase_chat_repository.dart +++ b/lib/repositories/firebase_chat_repository.dart @@ -1,43 +1,34 @@ -import 'dart:developer'; -import 'package:cloud_firestore/cloud_firestore.dart'; +import 'dart:async'; import 'package:prosapp_web_app/models/chat_entity.dart'; import 'package:prosapp_web_app/models/message_entity.dart'; +import 'package:prosapp_web_app/services/api_service.dart'; +// ponytail: renamed to ApiChatRepository but kept filename to avoid breaking imports class FirebaseChatRepository { - final chatCollection = FirebaseFirestore.instance.collection('chats'); + final _api = ApiService.instance; - Stream getChatById(String chatId) { - return chatCollection.doc(chatId).snapshots().map((snapshot) { + Stream getChatById(String chatId) async* { + while (true) { try { - if (snapshot.exists) { - return ChatEntity.fromDocument(snapshot.data()!); - } else { - return null; - } - } catch (e) { - log(e.toString()); - return null; + final data = await _api.get('/chats/$chatId'); + yield ChatEntity.fromDocument(data as Map); + } catch (_) { + yield null; } - }); + await Future.delayed(const Duration(seconds: 3)); + } } - Future createNewChat( - String chatId, String userId, String professionalId) async { - ChatEntity chat = ChatEntity( - id: chatId, - userId: userId, - professionalId: professionalId, - messages: const [], - ); - - await chatCollection.doc(chatId).set(chat.toDocument()); - - return chat; + Future createNewChat(String chatId, String userId, String professionalId) async { + final data = await _api.post('/chats', { + 'id': chatId, + 'user_id': userId, + 'professional_id': professionalId, + }); + return ChatEntity.fromDocument(data as Map); } - sendMessage(String chatId, MessageEntity message) { - chatCollection.doc(chatId).update({ - 'messages': FieldValue.arrayUnion([message.toDocument()]) - }); + Future sendMessage(String chatId, MessageEntity message) async { + await _api.post('/chats/$chatId/messages', message.toDocument()); } } diff --git a/lib/repositories/firebase_score_repository.dart b/lib/repositories/firebase_score_repository.dart index 0c8d2cc..501d546 100644 --- a/lib/repositories/firebase_score_repository.dart +++ b/lib/repositories/firebase_score_repository.dart @@ -1,91 +1,52 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:firebase_auth/firebase_auth.dart'; import 'package:prosapp_web_app/models/comment_entity.dart'; import 'package:prosapp_web_app/models/score_entity.dart'; +import 'package:prosapp_web_app/services/api_service.dart'; +// ponytail: renamed to ApiScoreRepository but kept filename to avoid breaking imports class FirebaseScoreRepository { - final reputationsCollection = - FirebaseFirestore.instance.collection('reputations'); - - final commentsCollection = FirebaseFirestore.instance.collection('comments'); + final _api = ApiService.instance; Future getReputationByUserId(String userId) async { try { - final snap = await reputationsCollection.doc(userId).get(); - return ReputationEntity.fromDocument(snap.data()!); + final data = await _api.get('/comments/reputation/$userId'); + return ReputationEntity.fromDocument(data as Map); } catch (e) { - return const ReputationEntity( - total: 0, - average: 0, - totalPro: 0, - averagePro: 0, - ); + return const ReputationEntity(total: 0, average: 0, totalPro: 0, averagePro: 0); } } - Stream streamReputation() { - return FirebaseAuth.instance.userChanges().asyncMap((user) async { - if (user != null) { - return await getReputationByUserId(user.uid); - } else { - return const ReputationEntity( - total: 0, - average: 0, - totalPro: 0, - averagePro: 0, - ); + Stream streamReputation(String userId) async* { + while (true) { + yield await getReputationByUserId(userId); + await Future.delayed(const Duration(seconds: 10)); + } + } + + Stream> getScoresForUser(String userId) async* { + while (true) { + try { + final data = await _api.get('/comments?destination_id=$userId&is_from_user=false') as List; + yield data.map((e) => CommentEntity.fromDocument(e as Map)).toList(); + } catch (_) { + yield []; } - }); + await Future.delayed(const Duration(seconds: 10)); + } } - Stream> getScoresForUser(String userId) { - return commentsCollection - .where('destination_id', isEqualTo: userId) - .where('is_from_user', isEqualTo: false) - .snapshots() - .map((querySnapshot) => querySnapshot.docs - .map((doc) => CommentEntity.fromDocument(doc.data())) - .toList()); - } - - Stream> getScoresForProfessional(String userId) { - return commentsCollection - .where('destination_id', isEqualTo: userId) - .where('is_from_user', isEqualTo: true) - .snapshots() - .map((querySnapshot) => querySnapshot.docs - .map((doc) => CommentEntity.fromDocument(doc.data())) - .toList()); + Stream> getScoresForProfessional(String userId) async* { + while (true) { + try { + final data = await _api.get('/comments?destination_id=$userId&is_from_user=true') as List; + yield data.map((e) => CommentEntity.fromDocument(e as Map)).toList(); + } catch (_) { + yield []; + } + await Future.delayed(const Duration(seconds: 10)); + } } Future addComment(CommentEntity comment) async { - await commentsCollection.add(comment.toDocument()); - - final query = await commentsCollection - .where('destination_id', isEqualTo: comment.destinationId) - .where('is_from_user', isEqualTo: comment.isFromUser) - .get(); - - var total = 0.0; - var count = 0; - for (var doc in query.docs) { - final comment = CommentEntity.fromDocument(doc.data()); - total += comment.score; - count++; - } - - if (count > 0) { - final average = total / count; - if (comment.isFromUser) { - await reputationsCollection.doc(comment.destinationId).set( - {'total_pro': count, 'average_pro': average}, - SetOptions(merge: true)); - } else { - await reputationsCollection.doc(comment.destinationId).set({ - 'total': count, - 'average': average, - }, SetOptions(merge: true)); - } - } + await _api.post('/comments', comment.toDocument()); } } diff --git a/lib/services/api_service.dart b/lib/services/api_service.dart new file mode 100644 index 0000000..baf4d5e --- /dev/null +++ b/lib/services/api_service.dart @@ -0,0 +1,73 @@ +import 'dart:convert'; +import 'dart:typed_data'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:http/http.dart' as http; +import 'package:prosapp_web_app/services/local_storage.dart'; + +class ApiService { + ApiService._(); + static final instance = ApiService._(); + + static String get baseUrl => dotenv.env['API_BASE_URL'] ?? 'https://backend.prosapp.co/api/v1'; + + Future getToken() => Future.value(LocalStorage.prefs.getString('jwt_token')); + + Future saveToken(String token) => LocalStorage.prefs.setString('jwt_token', token); + + Future deleteToken() => LocalStorage.prefs.remove('jwt_token'); + + Future> _headers() async { + final token = await getToken(); + return { + 'Content-Type': 'application/json', + if (token != null) 'Authorization': 'Bearer $token', + }; + } + + dynamic _parse(http.Response res) { + final body = jsonDecode(res.body); + if (res.statusCode >= 200 && res.statusCode < 300) return body; + throw Exception(body['message'] ?? 'Error ${res.statusCode}'); + } + + Future get(String path) async { + final res = await http.get(Uri.parse('$baseUrl$path'), headers: await _headers()); + return _parse(res); + } + + Future post(String path, Map body) async { + final res = await http.post( + Uri.parse('$baseUrl$path'), + headers: await _headers(), + body: jsonEncode(body), + ); + return _parse(res); + } + + Future patch(String path, Map body) async { + final res = await http.patch( + Uri.parse('$baseUrl$path'), + headers: await _headers(), + body: jsonEncode(body), + ); + return _parse(res); + } + + Future delete(String path) async { + final res = await http.delete(Uri.parse('$baseUrl$path'), headers: await _headers()); + return _parse(res); + } + + Future upload(Uint8List bytes, String filename) async { + final token = await getToken(); + final req = http.MultipartRequest('POST', Uri.parse('$baseUrl/storage/upload')); + if (token != null) req.headers['Authorization'] = 'Bearer $token'; + req.files.add(http.MultipartFile.fromBytes('file', bytes, filename: filename)); + final streamed = await req.send(); + final res = await http.Response.fromStream(streamed); + if (res.statusCode >= 200 && res.statusCode < 300) { + return (jsonDecode(res.body) as Map)['url'] as String?; + } + return null; + } +} diff --git a/lib/ui/views/chat_view.dart b/lib/ui/views/chat_view.dart index c3562fd..5372c26 100644 --- a/lib/ui/views/chat_view.dart +++ b/lib/ui/views/chat_view.dart @@ -1,5 +1,5 @@ -import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; +import 'package:prosapp_web_app/providers/auth_provider.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import 'package:intl/intl.dart'; import 'package:prosapp_web_app/models/message_entity.dart'; @@ -131,13 +131,13 @@ class ChatView extends StatelessWidget { padding: const EdgeInsets.only(top: 10), reverse: true, child: Column( - children: _messagesList(chat.messages), + children: _messagesList(chat.messages, Provider.of(context, listen: false).user!.id), ), ), ), _MessageInput( serviceId: serviceId, - userId: FirebaseAuth.instance.currentUser!.uid), + userId: Provider.of(context, listen: false).user!.id), ], ), ), @@ -163,10 +163,10 @@ class ChatView extends StatelessWidget { return resultado; } - List _messagesList(List messages) { + List _messagesList(List messages, String currentUserId) { return messages .map( - (e) => e.ownerId != FirebaseAuth.instance.currentUser!.uid + (e) => e.ownerId != currentUserId ? ListTile( title: Column( mainAxisAlignment: MainAxisAlignment.start, diff --git a/lib/ui/views/dashboard_view.dart b/lib/ui/views/dashboard_view.dart index 35906e4..85eab13 100644 --- a/lib/ui/views/dashboard_view.dart +++ b/lib/ui/views/dashboard_view.dart @@ -1,8 +1,7 @@ import 'dart:async'; import 'dart:convert'; - -import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:intl/intl.dart'; +import 'package:prosapp_web_app/services/api_service.dart'; import 'package:prosapp_web_app/models/schedules_entity.dart'; import 'package:prosapp_web_app/models/service.dart'; import 'package:prosapp_web_app/models/service_location_preferences.dart'; @@ -142,7 +141,7 @@ class _DashboardViewState extends State { latitude: latitude, longitude: longitude, day: selectedDay.toString(), - createdAt: Timestamp.now(), + createdAt: DateTime.now().toIso8601String(), description: '', range1Hour1: selectedHour!, range1Hour2: selectedHour!.add(hour: 2), @@ -153,9 +152,7 @@ class _DashboardViewState extends State { print('debug 1'); - await FirebaseFirestore.instance - .collection('services') - .add(service.toDocument()); + await ApiService.instance.post('/services', service.toDocument()); print('debug 2'); diff --git a/lib/ui/views/phone_login_view.dart b/lib/ui/views/phone_login_view.dart index 351c330..7d36d84 100644 --- a/lib/ui/views/phone_login_view.dart +++ b/lib/ui/views/phone_login_view.dart @@ -64,7 +64,7 @@ class PhoneLoginView extends StatelessWidget { showDialog( context: context, builder: (context) => - _buildOtpModal(context, authProvider), + _buildOtpModal(context, authProvider, phoneFormProvider.phone), ); } }, @@ -89,7 +89,7 @@ class PhoneLoginView extends StatelessWidget { ); } - Widget _buildOtpModal(BuildContext context, AuthProvider authProvider) { + Widget _buildOtpModal(BuildContext context, AuthProvider authProvider, String phone) { final _otpController = TextEditingController(); return AlertDialog( @@ -111,7 +111,7 @@ class PhoneLoginView extends StatelessWidget { final otp = _otpController.text.trim(); if (otp.isNotEmpty) { - await authProvider.signInWithOTP(otp); + await authProvider.signInWithOTP(phone, otp); Navigator.of(context).pop(); } else { ScaffoldMessenger.of(context).showSnackBar( diff --git a/lib/ui/views/phone_view.dart b/lib/ui/views/phone_view.dart index 0d6252e..b9eccba 100644 --- a/lib/ui/views/phone_view.dart +++ b/lib/ui/views/phone_view.dart @@ -77,7 +77,7 @@ class PhoneView extends StatelessWidget { showDialog( context: context, builder: (context) => _buildOtpModal( - context, authProvider), + context, authProvider, phoneFormProvider.phone), ); } }, @@ -102,7 +102,7 @@ class PhoneView extends StatelessWidget { ); } - Widget _buildOtpModal(BuildContext context, AuthProvider authProvider) { + Widget _buildOtpModal(BuildContext context, AuthProvider authProvider, String phone) { final _otpController = TextEditingController(); return AlertDialog( @@ -124,7 +124,7 @@ class PhoneView extends StatelessWidget { final otp = _otpController.text.trim(); if (otp.isNotEmpty) { - await authProvider.linkPhoneWithOTP(otp); + await authProvider.linkPhoneWithOTP(phone, otp); Navigator.of(context).pop(); } else { ScaffoldMessenger.of(context).showSnackBar( diff --git a/lib/ui/views/rating_view.dart b/lib/ui/views/rating_view.dart index 6b95117..d756eb9 100644 --- a/lib/ui/views/rating_view.dart +++ b/lib/ui/views/rating_view.dart @@ -1,4 +1,4 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; + import 'package:flutter/material.dart'; import 'package:prosapp_web_app/models/comment_entity.dart'; import 'package:prosapp_web_app/providers/score_provider.dart'; @@ -181,7 +181,7 @@ class _RatingViewState extends State { score: _rating, isFromUser: true, serviceId: widget.serviceId, - createdAt: Timestamp.now(), + createdAt: DateTime.now().toIso8601String(), authorId: service.userId, destinationId: service.professionalId, ); @@ -200,7 +200,7 @@ class _RatingViewState extends State { score: _rating, isFromUser: false, serviceId: widget.serviceId, - createdAt: Timestamp.now(), + createdAt: DateTime.now().toIso8601String(), authorId: service.professionalId, destinationId: service.userId, ); diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index a172cdb..d993eb7 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,21 +5,13 @@ import FlutterMacOS import Foundation -import cloud_firestore import file_selector_macos -import firebase_auth -import firebase_core -import firebase_storage import path_provider_foundation import shared_preferences_foundation import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) - FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin")) - FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) - FLTFirebaseStoragePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseStoragePlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 1060826..57973be 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,14 +1,6 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - _flutterfire_internals: - dependency: transitive - description: - name: _flutterfire_internals - sha256: a315d1c444402c3fa468de626d33a1c666041c87e9e195e8fb355b7084aefcc1 - url: "https://pub.dev" - source: hosted - version: "1.3.38" async: dependency: transitive description: @@ -41,30 +33,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.2" - cloud_firestore: - dependency: "direct main" - description: - name: cloud_firestore - sha256: "1232370ad04c21c699d0e73b2dc2e1c3b49258f89a16f0119036fd3c6e8aa2f5" - url: "https://pub.dev" - source: hosted - version: "5.0.2" - cloud_firestore_platform_interface: - dependency: transitive - description: - name: cloud_firestore_platform_interface - sha256: cfc64ae4a48bbb0ff6730b04f2d4653043c7a9b9008a991b1f2012a534b79e26 - url: "https://pub.dev" - source: hosted - version: "6.2.8" - cloud_firestore_web: - dependency: transitive - description: - name: cloud_firestore_web - sha256: "3db4e4c10feae18d80da86982781578c8e76cb6a43cf83110d8d6a62af9a952a" - url: "https://pub.dev" - source: hosted - version: "4.0.2" collection: dependency: transitive description: @@ -169,78 +137,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.3+1" - firebase_auth: - dependency: "direct main" - description: - name: firebase_auth - sha256: "087fdcb54b0af6f4c5c756e1db4f90e9b65871b9b3a75fabaa0e0ee578301669" - url: "https://pub.dev" - source: hosted - version: "5.1.1" - firebase_auth_platform_interface: - dependency: transitive - description: - name: firebase_auth_platform_interface - sha256: "8fac689f71ac3489a785579e99a4bad24a93ad3d78c313fb786ee517012d25f1" - url: "https://pub.dev" - source: hosted - version: "7.4.1" - firebase_auth_web: - dependency: transitive - description: - name: firebase_auth_web - sha256: "486b2527fcfcab01278378d8d4791f4f7bee8a9f15bf35e801ba08fbdd84c234" - url: "https://pub.dev" - source: hosted - version: "5.12.3" - firebase_core: - dependency: "direct main" - description: - name: firebase_core - sha256: "1e06b0538ab3108a61d895ee16951670b491c4a94fce8f2d30e5de7a5eca4b28" - url: "https://pub.dev" - source: hosted - version: "3.1.1" - firebase_core_platform_interface: - dependency: transitive - description: - name: firebase_core_platform_interface - sha256: "1003a5a03a61fc9a22ef49f37cbcb9e46c86313a7b2e7029b9390cf8c6fc32cb" - url: "https://pub.dev" - source: hosted - version: "5.1.0" - firebase_core_web: - dependency: transitive - description: - name: firebase_core_web - sha256: "6643fe3dbd021e6ccfb751f7882b39df355708afbdeb4130fc50f9305a9d1a3d" - url: "https://pub.dev" - source: hosted - version: "2.17.2" - firebase_storage: - dependency: "direct main" - description: - name: firebase_storage - sha256: "01fdcef335d2c86a265e9eb3c5b3b489ddc5589e7fc18a74df84b31be9f0c15b" - url: "https://pub.dev" - source: hosted - version: "12.1.0" - firebase_storage_platform_interface: - dependency: transitive - description: - name: firebase_storage_platform_interface - sha256: "8fdbfc63af3441434f33a420a304a670b464ff71b8f12fccc80accba1378ca3b" - url: "https://pub.dev" - source: hosted - version: "5.1.25" - firebase_storage_web: - dependency: transitive - description: - name: firebase_storage_web - sha256: bb9a387ae26bf7358e118f191ee22167b30217cad551184592cc73e7f73bd470 - url: "https://pub.dev" - source: hosted - version: "3.9.10" fluro: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 7960207..2328499 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -28,13 +28,9 @@ environment: # the latest version available on pub.dev. To see which dependencies have newer # versions available, run `flutter pub outdated`. dependencies: - cloud_firestore: ^5.0.2 cupertino_icons: ^1.0.6 email_validator: ^3.0.0 file_picker: ^8.0.6 - firebase_auth: ^5.1.1 - firebase_core: ^3.1.1 - firebase_storage: ^12.1.0 fluro: ^2.0.5 flutter: sdk: flutter diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 3e6795e..043a96f 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,24 +6,12 @@ #include "generated_plugin_registrant.h" -#include #include -#include -#include -#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { - CloudFirestorePluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("CloudFirestorePluginCApi")); FileSelectorWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("FileSelectorWindows")); - FirebaseAuthPluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi")); - FirebaseCorePluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); - FirebaseStoragePluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("FirebaseStoragePluginCApi")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 9615bc9..a95e267 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,11 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST - cloud_firestore file_selector_windows - firebase_auth - firebase_core - firebase_storage url_launcher_windows )