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:
co-authored by
Claude Sonnet 4.6
parent
726cf12fd2
commit
733384091c
@@ -1,6 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:user_repository/user_repository.dart';
|
||||
@@ -86,18 +85,18 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
} else {
|
||||
switch (error) {
|
||||
case UpdatePassworErros.credentialsWrong:
|
||||
emit(const AuthStateFailure(message: "Contraseña incorrecta"));
|
||||
emit(const AuthStateFailure(message: "Contrasena incorrecta"));
|
||||
break;
|
||||
case UpdatePassworErros.userNotFound:
|
||||
emit(const AuthStateFailure(message: "Usuario no encontrado"));
|
||||
break;
|
||||
case UpdatePassworErros.unknown:
|
||||
emit(const AuthStateFailure(message: "Error inesperado. 🥸"));
|
||||
emit(const AuthStateFailure(message: "Error inesperado."));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
emit(const AuthStateFailure(message: "Error inesperado. 🥸"));
|
||||
emit(const AuthStateFailure(message: "Error inesperado."));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,81 +109,33 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
in phoneVerificationService.verifyPhoneNumber(event.phoneNumber)) {
|
||||
switch (event.type) {
|
||||
case PhoneAuthEventType.verificationCompleted:
|
||||
AuthCredential credential = event.data;
|
||||
print('Verificación completada. Credencial: $credential');
|
||||
final credential = event.data;
|
||||
print('Verificacion completada. Credencial: $credential');
|
||||
break;
|
||||
case PhoneAuthEventType.verificationFailed:
|
||||
FirebaseAuthException exception = event.data;
|
||||
print('Verificación fallida. Excepción: $exception');
|
||||
emit(AuthStateFailure(message: "Error inesperado. 🥸 $exception"));
|
||||
return; // Detener la ejecución aquí
|
||||
final exception = event.data;
|
||||
print('Verificacion fallida. Excepcion: $exception');
|
||||
emit(AuthStateFailure(message: "Error inesperado. $exception"));
|
||||
return;
|
||||
case PhoneAuthEventType.codeAutoRetrievalTimeout:
|
||||
String verificationId = event.data;
|
||||
print(
|
||||
'Tiempo de espera agotado para recuperar el código. ID: $verificationId');
|
||||
final verificationId = event.data as String;
|
||||
print('Tiempo de espera agotado. ID: $verificationId');
|
||||
emit(const AuthStateFailure(
|
||||
message: "Tiempo de espera agotado. 🥸",
|
||||
message: "Tiempo de espera agotado.",
|
||||
));
|
||||
break;
|
||||
case PhoneAuthEventType.codeSent:
|
||||
Map<String, dynamic> eventData = event.data;
|
||||
String verificationId = eventData['verificationId'];
|
||||
int? resendToken = eventData['resendToken'];
|
||||
print(
|
||||
'Código enviado. ID: $verificationId, resendToken: $resendToken');
|
||||
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;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
emit(const AuthStateFailure(message: "Error inesperado. 🥸"));
|
||||
}
|
||||
}
|
||||
|
||||
void _linkWithPhoneNumber3(
|
||||
LinkWithPhoneNumber event, Emitter<AuthState> emit) async {
|
||||
emit(AuthStateProcess());
|
||||
|
||||
try {
|
||||
StreamSubscription<PhoneAuthEvent> subscription = phoneVerificationService
|
||||
.verifyPhoneNumber(event.phoneNumber)
|
||||
.listen((event) async {
|
||||
switch (event.type) {
|
||||
case PhoneAuthEventType.verificationCompleted:
|
||||
AuthCredential credential = event.data;
|
||||
print('Verificación completada. Credencial: $credential');
|
||||
break;
|
||||
case PhoneAuthEventType.verificationFailed:
|
||||
FirebaseAuthException exception = event.data;
|
||||
print('Verificación fallida. Excepción: $exception');
|
||||
break;
|
||||
case PhoneAuthEventType.codeAutoRetrievalTimeout:
|
||||
String verificationId = event.data;
|
||||
print(
|
||||
'Tiempo de espera agotado para recuperar el código. ID: $verificationId');
|
||||
break;
|
||||
case PhoneAuthEventType.codeSent:
|
||||
Map<String, dynamic> eventData = event.data;
|
||||
String verificationId = eventData['verificationId'];
|
||||
int? resendToken = eventData['resendToken'];
|
||||
print(
|
||||
'Código enviado. ID: $verificationId, resendToken: $resendToken');
|
||||
_verificationId = verificationId;
|
||||
emit(const AuthStateVerifyOAuth(false));
|
||||
break;
|
||||
}
|
||||
|
||||
if (event.type == PhoneAuthEventType.verificationFailed) {
|
||||
// Detener la suscripción si la verificación falla
|
||||
// subscription.cancel();
|
||||
emit(const AuthStateFailure(message: "Error inesperado. 🥸"));
|
||||
}
|
||||
});
|
||||
|
||||
// await _userRepository
|
||||
} catch (e) {
|
||||
emit(const AuthStateFailure(message: "Error inesperado. 🥸"));
|
||||
emit(const AuthStateFailure(message: "Error inesperado."));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +144,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
emit(AuthStateProcess());
|
||||
try {
|
||||
final bool isVerified = await _userRepository.linkWithOTP(
|
||||
event.phoneNumber, _verificationId!, event.code);
|
||||
event.phoneNumber, _verificationId ?? '', event.code);
|
||||
|
||||
if (isVerified) {
|
||||
emit(AuthStateSuccess());
|
||||
@@ -201,34 +152,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
emit(const AuthStateVerifyOAuth(true));
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is FirebaseAuthException) {
|
||||
switch (e.code) {
|
||||
case "invalid-verification-code":
|
||||
emit(const AuthStateFailure(
|
||||
message: "Código de verificación incorrecto. 🥸",
|
||||
));
|
||||
break;
|
||||
|
||||
case "provider-already-linked":
|
||||
emit(const AuthStateFailure(
|
||||
message: "Cuenta ya vinculada. 🥸",
|
||||
));
|
||||
break;
|
||||
|
||||
case "credential-already-in-use":
|
||||
emit(const AuthStateFailure(
|
||||
message:
|
||||
"Este numero ya se encuentra registrado con otra cuenta. 🥸",
|
||||
));
|
||||
break;
|
||||
|
||||
default:
|
||||
emit(AuthStateFailure(message: "Error inesperado. 🥸 $e"));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
emit(AuthStateFailure(message: "Error inesperado. 🥸 $e"));
|
||||
}
|
||||
emit(AuthStateFailure(message: "Error inesperado. $e"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@ part 'chat_event.dart';
|
||||
part 'chat_state.dart';
|
||||
|
||||
class ChatBloc extends Bloc<ChatEvent, ChatState> {
|
||||
final FirebaseChatRepository _chatRepository;
|
||||
final ApiChatRepository _chatRepository;
|
||||
|
||||
ChatBloc({
|
||||
required FirebaseChatRepository chatRepository,
|
||||
required ApiChatRepository chatRepository,
|
||||
}) : _chatRepository = chatRepository,
|
||||
super(ChatInitial()) {
|
||||
on<LoadChatEvent>(_onLoadChatEvent);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -10,11 +10,11 @@ part 'professional_event.dart';
|
||||
part 'professional_state.dart';
|
||||
|
||||
class ProfessionalBloc extends Bloc<ProfessionalEvent, ProfessionalState> {
|
||||
final FirebaseProfessionalRepository _professionalRepository;
|
||||
final ApiProfessionalRepository _professionalRepository;
|
||||
final UserRepository _userRepository;
|
||||
|
||||
ProfessionalBloc(
|
||||
{required FirebaseProfessionalRepository professionalRepository,
|
||||
{required ApiProfessionalRepository professionalRepository,
|
||||
required UserRepository userRepository})
|
||||
: _professionalRepository = professionalRepository,
|
||||
_userRepository = userRepository,
|
||||
|
||||
@@ -9,11 +9,11 @@ part 'professional_list_state.dart';
|
||||
class ProfessionalListBloc
|
||||
extends Bloc<ProfessionalListEvent, ProfessionalListState> {
|
||||
final UserRepository _userRepository;
|
||||
final FirebaseProfessionalRepository _firebaseProfessionalRepository;
|
||||
final ApiProfessionalRepository _firebaseProfessionalRepository;
|
||||
|
||||
ProfessionalListBloc({
|
||||
required UserRepository userRepository,
|
||||
required FirebaseProfessionalRepository firebaseProfessonalRepository,
|
||||
required ApiProfessionalRepository firebaseProfessonalRepository,
|
||||
}) : _userRepository = userRepository,
|
||||
_firebaseProfessionalRepository = firebaseProfessonalRepository,
|
||||
super(ProfessionalListInitial()) {
|
||||
|
||||
@@ -7,10 +7,10 @@ part 'professional_profile_state.dart';
|
||||
|
||||
class ProfessionalProfileBloc
|
||||
extends Bloc<ProfessionalProfileEvent, ProfessionalProfileState> {
|
||||
final FirebaseProfessionalRepository _professionalRepository;
|
||||
final ApiProfessionalRepository _professionalRepository;
|
||||
|
||||
ProfessionalProfileBloc(
|
||||
{required FirebaseProfessionalRepository professionalRepository})
|
||||
{required ApiProfessionalRepository professionalRepository})
|
||||
: _professionalRepository = professionalRepository,
|
||||
super((UpdateProfessionalInfoInitial())) {
|
||||
on<UpdateProfessionalBannerInfo>(_onUpdateProfessionalBannerInfo);
|
||||
|
||||
@@ -9,11 +9,11 @@ part 'score_event.dart';
|
||||
part 'score_state.dart';
|
||||
|
||||
class ScoreBloc extends Bloc<ScoreEvent, ScoreState> {
|
||||
final FirebaseScoreRepository _scoreRepository;
|
||||
final ApiScoreRepository _scoreRepository;
|
||||
final UserRepository _userRepository;
|
||||
|
||||
ScoreBloc({
|
||||
required FirebaseScoreRepository scoreRepository,
|
||||
required ApiScoreRepository scoreRepository,
|
||||
required UserRepository userRepository,
|
||||
}) : _scoreRepository = scoreRepository,
|
||||
_userRepository = userRepository,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
@@ -13,14 +12,14 @@ part 'service_event.dart';
|
||||
part 'service_state.dart';
|
||||
|
||||
class ServiceBloc extends Bloc<ServiceEvent, ServiceState> {
|
||||
final FirebaseServiceRepository _serviceRepository;
|
||||
final ApiServiceRepository _serviceRepository;
|
||||
final UserRepository _userRepository;
|
||||
final FirebaseProfessionalRepository _professionalRepository;
|
||||
final ApiProfessionalRepository _professionalRepository;
|
||||
|
||||
ServiceBloc({
|
||||
required FirebaseServiceRepository serviceRepository,
|
||||
required ApiServiceRepository serviceRepository,
|
||||
required UserRepository userRepository,
|
||||
required FirebaseProfessionalRepository professionRepository,
|
||||
required ApiProfessionalRepository professionRepository,
|
||||
}) : _serviceRepository = serviceRepository,
|
||||
_userRepository = userRepository,
|
||||
_professionalRepository = professionRepository,
|
||||
|
||||
@@ -117,7 +117,7 @@ class CreateService extends ServiceEvent {
|
||||
final double latitude;
|
||||
final double longitude;
|
||||
final String day;
|
||||
final Timestamp createdAt;
|
||||
final String createdAt;
|
||||
final String description;
|
||||
final TimeOfDay range1Hour1;
|
||||
final TimeOfDay range1Hour2;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -233,9 +232,9 @@ class GeneralDrawer extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
future: Injector.appInstance
|
||||
.get<FirebaseServiceRepository>()
|
||||
.get<ApiServiceRepository>()
|
||||
.countPendingServicesForProfessional(
|
||||
FirebaseAuth.instance.currentUser!.uid),
|
||||
ApiUserRepository.currentUserId ?? ''),
|
||||
)
|
||||
: const Icon(
|
||||
Icons.keyboard_arrow_right,
|
||||
@@ -477,9 +476,9 @@ class GeneralDrawer extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
future: Injector.appInstance
|
||||
.get<FirebaseServiceRepository>()
|
||||
.get<ApiServiceRepository>()
|
||||
.countPendingServicesForProfessional(
|
||||
FirebaseAuth.instance.currentUser!.uid),
|
||||
ApiUserRepository.currentUserId ?? ''),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -23,7 +23,7 @@ class _GeneralReputationState extends State<GeneralReputation> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
final repository = Injector.appInstance.get<FirebaseScoreRepository>();
|
||||
final repository = Injector.appInstance.get<ApiScoreRepository>();
|
||||
reputation = repository.getReputationByUserId(widget.userId);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
const String GOOGLE_MAPS_API_KEY = 'AIzaSyCW_og6qQ8W8G-5_BxIS4sBnl8cLkjL95s';
|
||||
|
||||
const String API_BASE_URL = String.fromEnvironment('API_BASE_URL', defaultValue: 'http://localhost:3000/api/v1');
|
||||
|
||||
const String MAP_STYLE = '''
|
||||
[
|
||||
{
|
||||
|
||||
+15
-20
@@ -1,5 +1,4 @@
|
||||
import 'package:chat_repository/chat_repository.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:injector/injector.dart';
|
||||
import 'package:profession_repository/profession_repository.dart';
|
||||
import 'package:professional_repository/professional_repository.dart';
|
||||
@@ -29,20 +28,20 @@ class AppDI {
|
||||
final injector = Injector.appInstance;
|
||||
|
||||
injector.registerSingleton<UserRepository>(
|
||||
(() => FirebaseUserRepository(FirebaseAuth.instance)));
|
||||
(() => ApiUserRepository()));
|
||||
|
||||
injector.registerSingleton<CityRepository>(() => FirebaseCityRepository());
|
||||
injector.registerSingleton<CityRepository>(() => ApiCityRepository());
|
||||
|
||||
injector.registerSingleton<ProfessionRepository>(
|
||||
() => FirebaseProfessionRepository());
|
||||
() => ApiProfessionRepository());
|
||||
|
||||
injector.registerSingleton<SettingRepository>(
|
||||
() => FirebaseSettingRepository());
|
||||
() => ApiSettingRepository());
|
||||
|
||||
injector.registerSingleton(() => FirebaseProfessionalRepository());
|
||||
injector.registerSingleton(() => FirebaseServiceRepository());
|
||||
injector.registerSingleton(() => FirebaseChatRepository());
|
||||
injector.registerSingleton(() => FirebaseScoreRepository());
|
||||
injector.registerSingleton(() => ApiProfessionalRepository());
|
||||
injector.registerSingleton(() => ApiServiceRepository());
|
||||
injector.registerSingleton(() => ApiChatRepository());
|
||||
injector.registerSingleton(() => ApiScoreRepository());
|
||||
|
||||
injector.registerSingleton<AuthenticationBloc>((() =>
|
||||
AuthenticationBloc(myUserRepository: injector.get<UserRepository>())));
|
||||
@@ -60,7 +59,8 @@ class AppDI {
|
||||
);
|
||||
injector.registerSingleton(
|
||||
() => NotificationBloc(
|
||||
requestLocalNotificationPermission: LocalNotifications.requestPermissionLocalNotifications,
|
||||
requestLocalNotificationPermission:
|
||||
LocalNotifications.requestPermissionLocalNotifications,
|
||||
showLocalNotification: LocalNotifications.showLocalNotification,
|
||||
),
|
||||
);
|
||||
@@ -84,31 +84,26 @@ class AppDI {
|
||||
() => ProfessionalListBloc(
|
||||
userRepository: injector.get<UserRepository>(),
|
||||
firebaseProfessonalRepository:
|
||||
injector.get<FirebaseProfessionalRepository>()),
|
||||
injector.get<ApiProfessionalRepository>()),
|
||||
);
|
||||
|
||||
injector.registerDependency<ChatBloc>(() => ChatBloc(
|
||||
chatRepository: injector.get<FirebaseChatRepository>(),
|
||||
chatRepository: injector.get<ApiChatRepository>(),
|
||||
));
|
||||
|
||||
injector.registerDependency<ServiceBloc>(
|
||||
() => ServiceBloc(
|
||||
serviceRepository: injector.get<FirebaseServiceRepository>(),
|
||||
serviceRepository: injector.get<ApiServiceRepository>(),
|
||||
userRepository: injector.get<UserRepository>(),
|
||||
professionRepository: injector.get<FirebaseProfessionalRepository>(),
|
||||
professionRepository: injector.get<ApiProfessionalRepository>(),
|
||||
),
|
||||
);
|
||||
|
||||
injector.registerDependency<ScoreBloc>(
|
||||
() => ScoreBloc(
|
||||
scoreRepository: injector.get<FirebaseScoreRepository>(),
|
||||
scoreRepository: injector.get<ApiScoreRepository>(),
|
||||
userRepository: injector.get<UserRepository>(),
|
||||
),
|
||||
);
|
||||
|
||||
// injector.registerSingleton((() => ScoreBloc(
|
||||
// firebaseScoreRepository: injector.get(),
|
||||
// userRepository: injector.get<UserRepository>(),
|
||||
// )));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'dart:convert';
|
||||
import 'package:prosappco/constansts.dart' show API_BASE_URL;
|
||||
|
||||
class LocalNotifications {
|
||||
static Future<void> requestPermissionLocalNotifications() async {
|
||||
@@ -76,25 +77,14 @@ class LocalNotifications {
|
||||
String token, String title, String body) async {
|
||||
try {
|
||||
http.Response response = await http.post(
|
||||
Uri.parse('https://fcm.googleapis.com/fcm/send'),
|
||||
Uri.parse('$API_BASE_URL/notifications/send'),
|
||||
headers: <String, String>{
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
'Authorization':
|
||||
'key=AAAAORdR-xU:APA91bF_wblg86jHAC-uexrXPHavYRlk5wge1Gf46m56V4J2D2L37Cp_hf46JZUzpvsWPSpqc5ewHelKI9LTifUG_s2mciMI6e5VLKo7E1R8btbNo7iaM9do2ctoyHKUm1atlZBdKaN2',
|
||||
},
|
||||
body: jsonEncode(
|
||||
<String, dynamic>{
|
||||
'notification': <String, dynamic>{
|
||||
'body': body,
|
||||
'title': title,
|
||||
|
||||
},
|
||||
'priority': 'high',
|
||||
'data': <String, dynamic>{
|
||||
'click_action': 'FLUTTER_NOTIFICATION_CLICK',
|
||||
'id': '1',
|
||||
'status': 'done',
|
||||
},
|
||||
'title': title,
|
||||
'body': body,
|
||||
'to': token,
|
||||
},
|
||||
),
|
||||
|
||||
+1
-9
@@ -1,6 +1,4 @@
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:injector/injector.dart';
|
||||
@@ -14,19 +12,13 @@ import 'package:prosappco/blocs/profile_bloc/profile_bloc.dart';
|
||||
import 'package:prosappco/dependency/app_di.dart';
|
||||
import 'package:prosappco/local_notifications/local_notifications.dart';
|
||||
import 'simple_bloc_observer.dart';
|
||||
import 'firebase_options.dart';
|
||||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
await Firebase.initializeApp(
|
||||
options: DefaultFirebaseOptions.currentPlatform,
|
||||
); // Asegúrate de inicializar Firebase antes de cualquier otra operación relacionada con Firebase.
|
||||
|
||||
// Inicialización de notificaciones locales después de Firebase.
|
||||
// Inicializacion de notificaciones locales
|
||||
await LocalNotifications.initializeLocalNotifications();
|
||||
|
||||
FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
|
||||
|
||||
Bloc.observer = SimpleBlocObserver();
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
AppDI().register();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:chat_repository/chat_repository.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -111,7 +110,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
),
|
||||
),
|
||||
subtitle: widget.service.userId ==
|
||||
FirebaseAuth.instance.currentUser!.uid
|
||||
ApiUserRepository.currentUserId ?? ''
|
||||
? GeneralReputation(
|
||||
userId: widget.service.professionalId,
|
||||
builder: (context, reputation) {
|
||||
@@ -229,7 +228,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
|
||||
MessageEntity message = MessageEntity(
|
||||
ownerId:
|
||||
FirebaseAuth.instance.currentUser!.uid,
|
||||
ApiUserRepository.currentUserId ?? '',
|
||||
content: _messageController.text.trim(),
|
||||
createdAt: DateTime.now(),
|
||||
);
|
||||
@@ -272,7 +271,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
}
|
||||
|
||||
MessageEntity message = MessageEntity(
|
||||
ownerId: FirebaseAuth.instance.currentUser!.uid,
|
||||
ownerId: ApiUserRepository.currentUserId ?? '',
|
||||
content: _messageController.text.trim(),
|
||||
createdAt: DateTime.now(),
|
||||
);
|
||||
@@ -340,7 +339,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
List<Widget> _messagesList(List<MessageEntity> messages) {
|
||||
return messages
|
||||
.map(
|
||||
(e) => e.ownerId != FirebaseAuth.instance.currentUser!.uid
|
||||
(e) => e.ownerId != ApiUserRepository.currentUserId ?? ''
|
||||
? ListTile(
|
||||
title: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
@@ -437,12 +436,12 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
|
||||
Future<List<dynamic>> _getUserAndProfessionalInfo(
|
||||
ServiceEntity service) async {
|
||||
final userRepo = FirebaseUserRepository(FirebaseAuth.instance);
|
||||
final userRepo = Injector.appInstance.get<UserRepository>();
|
||||
|
||||
final MyUser? userInfo;
|
||||
final MyUser? myInfo;
|
||||
|
||||
if (FirebaseAuth.instance.currentUser!.uid == service.userId) {
|
||||
if ((ApiUserRepository.currentUserId ?? '') == service.userId) {
|
||||
userInfo = await userRepo.getMyUser(service.professionalId);
|
||||
myInfo = await userRepo.getMyUser(service.userId);
|
||||
} else {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:user_repository/user_repository.dart';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -173,13 +174,13 @@ class _ProfessionalListScreenState extends State<ProfessionalListScreen> {
|
||||
.toLowerCase()
|
||||
.contains(removeDiacritics(_searchController.text.toLowerCase())))
|
||||
.where((user) =>
|
||||
user.myUser.id != FirebaseAuth.instance.currentUser!.uid)
|
||||
user.myUser.id != ApiUserRepository.currentUserId ?? '')
|
||||
.where(
|
||||
(user) => user.professionalInfo.profession == _selectedProfession)
|
||||
.toList();
|
||||
// } else {
|
||||
// filteredUsers = state.users
|
||||
// // .where((user) => user.myUser.id != FirebaseAuth.instance.currentUser!.uid)
|
||||
// // .where((user) => user.myUser.id != ApiUserRepository.currentUserId ?? '')
|
||||
// .toList();
|
||||
// }
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:user_repository/user_repository.dart';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -28,7 +29,7 @@ class _ProfessionalPendingServiceListScreenState
|
||||
|
||||
serviceBloc = Injector.appInstance.get<ServiceBloc>();
|
||||
|
||||
serviceBloc.add(LoadPendingServicesForProfessional(FirebaseAuth.instance.currentUser!.uid));
|
||||
serviceBloc.add(LoadPendingServicesForProfessional(ApiUserRepository.currentUserId ?? ''));
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:user_repository/user_repository.dart';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -25,7 +26,7 @@ class _ProfessionalScoreListScreenState
|
||||
scoreBloc = Injector.appInstance.get<ScoreBloc>();
|
||||
|
||||
scoreBloc.add(LoadScoresForProfessionalEvent(
|
||||
userId: FirebaseAuth.instance.currentUser!.uid));
|
||||
userId: ApiUserRepository.currentUserId ?? ''));
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:user_repository/user_repository.dart';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -29,7 +30,7 @@ class _ProfessionalServiceHistoryListScreenState
|
||||
serviceBloc = Injector.appInstance.get<ServiceBloc>();
|
||||
|
||||
serviceBloc.add(LoadServicesHistoryForProfessional(
|
||||
FirebaseAuth.instance.currentUser!.uid));
|
||||
ApiUserRepository.currentUserId ?? ''));
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:user_repository/user_repository.dart';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -28,7 +29,7 @@ class _ProfessionalServiceListScreenState
|
||||
|
||||
serviceBloc = Injector.appInstance.get<ServiceBloc>();
|
||||
|
||||
serviceBloc.add(LoadServicesForProfessional(FirebaseAuth.instance.currentUser!.uid));
|
||||
serviceBloc.add(LoadServicesForProfessional(ApiUserRepository.currentUserId ?? ''));
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:user_repository/user_repository.dart';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -24,7 +25,7 @@ class _UserScoreListScreenState extends State<UserScoreListScreen> {
|
||||
scoreBloc = Injector.appInstance.get<ScoreBloc>();
|
||||
|
||||
scoreBloc.add(
|
||||
LoadScoresForUserEvent(userId: FirebaseAuth.instance.currentUser!.uid));
|
||||
LoadScoresForUserEvent(userId: ApiUserRepository.currentUserId ?? ''));
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:user_repository/user_repository.dart';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -29,7 +30,7 @@ class _UserServiceHistoryListScreenState
|
||||
serviceBloc = Injector.appInstance.get<ServiceBloc>();
|
||||
|
||||
serviceBloc.add(
|
||||
LoadServicesHistoryForUser(FirebaseAuth.instance.currentUser!.uid));
|
||||
LoadServicesHistoryForUser(ApiUserRepository.currentUserId ?? ''));
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:user_repository/user_repository.dart';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -27,7 +28,7 @@ class _UserServiceListScreenState extends State<UserServiceListScreen> {
|
||||
serviceBloc = Injector.appInstance.get<ServiceBloc>();
|
||||
|
||||
serviceBloc
|
||||
.add(LoadServicesForUser(FirebaseAuth.instance.currentUser!.uid));
|
||||
.add(LoadServicesForUser(ApiUserRepository.currentUserId ?? ''));
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -28,7 +27,7 @@ class ProfessionalCalendarScreen extends StatefulWidget {
|
||||
class _ProfessionalCalendarScreenState extends State<ProfessionalCalendarScreen> {
|
||||
final settingRepository = Injector.appInstance.get<SettingRepository>();
|
||||
final serviceRepository =
|
||||
Injector.appInstance.get<FirebaseServiceRepository>();
|
||||
Injector.appInstance.get<ApiServiceRepository>();
|
||||
SettingEntity? settings;
|
||||
|
||||
DateTime today = DateTime.now();
|
||||
@@ -352,7 +351,7 @@ class _ProfessionalCalendarScreenState extends State<ProfessionalCalendarScreen>
|
||||
latitude: 0,
|
||||
longitude: 0,
|
||||
day: today.toString(),
|
||||
createdAt: Timestamp.now(),
|
||||
createdAt: DateTime.now().toIso8601String(),
|
||||
description: '',
|
||||
range1Hour1: time,
|
||||
range1Hour2: time.add(hour: 2),
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -33,7 +31,7 @@ class _ScoreScreenState extends State<ScoreScreen> {
|
||||
super.initState();
|
||||
_userInfoFuture = _getUserAndProfessionalInfo(widget.service);
|
||||
isProfessional =
|
||||
FirebaseAuth.instance.currentUser!.uid == widget.service.userId
|
||||
ApiUserRepository.currentUserId ?? '' == widget.service.userId
|
||||
? true
|
||||
: false;
|
||||
|
||||
@@ -304,33 +302,33 @@ class _ScoreScreenState extends State<ScoreScreen> {
|
||||
return FilledButton(
|
||||
onPressed: () {
|
||||
final CommentEntity comment = widget.service.userId ==
|
||||
FirebaseAuth.instance.currentUser!.uid
|
||||
ApiUserRepository.currentUserId ?? ''
|
||||
? CommentEntity(
|
||||
serviceId: widget.service.id!,
|
||||
authorId:
|
||||
FirebaseAuth.instance.currentUser!.uid,
|
||||
ApiUserRepository.currentUserId ?? '',
|
||||
isFromUser: true,
|
||||
score: _rating,
|
||||
destinationId: widget.service.professionalId,
|
||||
content: commentController.text.trim(),
|
||||
createdAt: Timestamp.now(),
|
||||
createdAt: DateTime.now().toIso8601String(),
|
||||
)
|
||||
: CommentEntity(
|
||||
serviceId: widget.service.id!,
|
||||
authorId:
|
||||
FirebaseAuth.instance.currentUser!.uid,
|
||||
ApiUserRepository.currentUserId ?? '',
|
||||
isFromUser: false,
|
||||
score: _rating,
|
||||
destinationId: widget.service.userId,
|
||||
content: commentController.text.trim(),
|
||||
createdAt: Timestamp.now(),
|
||||
createdAt: DateTime.now().toIso8601String(),
|
||||
);
|
||||
|
||||
BlocProvider.of<ScoreBloc>(context)
|
||||
.add(SendScoreEvent(comment: comment));
|
||||
|
||||
if (widget.service.userId ==
|
||||
FirebaseAuth.instance.currentUser!.uid) {
|
||||
ApiUserRepository.currentUserId ?? '') {
|
||||
context.read<ServiceBloc>().add(
|
||||
UpdateProfessionalScored(widget.service.id!));
|
||||
} else {
|
||||
@@ -392,11 +390,11 @@ class _ScoreScreenState extends State<ScoreScreen> {
|
||||
|
||||
Future<List<dynamic>> _getUserAndProfessionalInfo(
|
||||
ServiceEntity service) async {
|
||||
final userRepo = FirebaseUserRepository(FirebaseAuth.instance);
|
||||
final userRepo = Injector.appInstance.get<UserRepository>();
|
||||
|
||||
final MyUser? userInfo;
|
||||
|
||||
if (FirebaseAuth.instance.currentUser!.uid == service.userId) {
|
||||
if (ApiUserRepository.currentUserId ?? '' == service.userId) {
|
||||
userInfo = await userRepo.getMyUser(service.professionalId);
|
||||
} else {
|
||||
userInfo = await userRepo.getMyUser(service.userId);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:async';
|
||||
import 'package:community_material_icon/community_material_icon.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -848,7 +847,7 @@ class _ProfessionalServiceScreenState extends State<ProfessionalServiceScreen> {
|
||||
|
||||
Future<List<dynamic>> _getUserAndProfessionalInfo(
|
||||
ServiceEntity service) async {
|
||||
final userRepo = FirebaseUserRepository(FirebaseAuth.instance);
|
||||
final userRepo = Injector.appInstance.get<UserRepository>();
|
||||
final userInfo = await userRepo.getMyUser(service.userId);
|
||||
|
||||
return [userInfo];
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -484,16 +483,15 @@ class _ServiceScreenState extends State<ServiceScreen> {
|
||||
|
||||
Future<List<dynamic>> _getUserAndProfessionalInfo(
|
||||
ServiceEntity service) async {
|
||||
final userRepo = FirebaseUserRepository(FirebaseAuth.instance);
|
||||
final professionalRepo = FirebaseProfessionalRepository();
|
||||
if (FirebaseAuth.instance.currentUser!.uid == service.professionalId) {
|
||||
final userRepo = Injector.appInstance.get<UserRepository>();
|
||||
final professionalRepo = Injector.appInstance.get<ApiProfessionalRepository>();
|
||||
if ((ApiUserRepository.currentUserId ?? '') == service.professionalId) {
|
||||
final userInfo = await userRepo.getMyUser(service.userId);
|
||||
final professionalInfo =
|
||||
await professionalRepo.getProInfo(service.professionalId);
|
||||
|
||||
return [userInfo, professionalInfo];
|
||||
} else {
|
||||
final userRepo = FirebaseUserRepository(FirebaseAuth.instance);
|
||||
final userInfo = await userRepo.getMyUser(service.professionalId);
|
||||
|
||||
final professionalInfo =
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:async';
|
||||
import 'package:community_material_icon/community_material_icon.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -975,8 +974,8 @@ class _UserServiceScreenState extends State<UserServiceScreen> {
|
||||
|
||||
Future<List<dynamic>> _getUserAndProfessionalInfo(
|
||||
ServiceEntity service) async {
|
||||
final userRepo = FirebaseUserRepository(FirebaseAuth.instance);
|
||||
final professionalRepo = FirebaseProfessionalRepository();
|
||||
final userRepo = Injector.appInstance.get<UserRepository>();
|
||||
final professionalRepo = Injector.appInstance.get<ApiProfessionalRepository>();
|
||||
|
||||
final userInfo = await userRepo.getMyUser(service.professionalId);
|
||||
final professionalInfo =
|
||||
|
||||
@@ -22,7 +22,7 @@ class UserCalendarScreen extends StatefulWidget {
|
||||
class UserCalendarScreenState extends State<UserCalendarScreen> {
|
||||
final settingRepository = Injector.appInstance.get<SettingRepository>();
|
||||
final serviceRepository =
|
||||
Injector.appInstance.get<FirebaseServiceRepository>();
|
||||
Injector.appInstance.get<ApiServiceRepository>();
|
||||
SettingEntity? settings;
|
||||
|
||||
DateTime today = DateTime.now();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -549,7 +548,7 @@ class _UserMapScreenState extends State<UserMapScreen> {
|
||||
longitude: profesionalSeleccionado!
|
||||
.professionalInfo.longitude,
|
||||
day: fechaSeleccionada.toString(),
|
||||
createdAt: Timestamp.now(),
|
||||
createdAt: DateTime.now().toIso8601String(),
|
||||
description: _observationController.text,
|
||||
range1Hour1: horaSeleccionada!,
|
||||
range1Hour2:
|
||||
@@ -574,7 +573,7 @@ class _UserMapScreenState extends State<UserMapScreen> {
|
||||
longitude: profesionalSeleccionado!
|
||||
.professionalInfo.longitude,
|
||||
day: fechaSeleccionada.toString(),
|
||||
createdAt: Timestamp.now(),
|
||||
createdAt: DateTime.now().toIso8601String(),
|
||||
description: _observationController.text,
|
||||
range1Hour1: horaSeleccionada!,
|
||||
range1Hour2:
|
||||
@@ -597,7 +596,7 @@ class _UserMapScreenState extends State<UserMapScreen> {
|
||||
latitude: 0,
|
||||
longitude: 0,
|
||||
day: fechaSeleccionada.toString(),
|
||||
createdAt: Timestamp.now(),
|
||||
createdAt: DateTime.now().toIso8601String(),
|
||||
description: _observationController.text,
|
||||
range1Hour1: horaSeleccionada!,
|
||||
range1Hour2:
|
||||
@@ -617,7 +616,7 @@ class _UserMapScreenState extends State<UserMapScreen> {
|
||||
latitude: 0,
|
||||
longitude: 0,
|
||||
day: fechaSeleccionada.toString(),
|
||||
createdAt: Timestamp.now(),
|
||||
createdAt: DateTime.now().toIso8601String(),
|
||||
description: _observationController.text,
|
||||
range1Hour1: horaSeleccionada!,
|
||||
range1Hour2:
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -618,10 +617,10 @@ class _UserServiceScreenState extends State<UserServiceScreen> {
|
||||
|
||||
Future<List<dynamic>> _getUserAndProfessionalInfo(
|
||||
ServiceEntity service) async {
|
||||
final userRepo = FirebaseUserRepository(FirebaseAuth.instance);
|
||||
final userRepo = Injector.appInstance.get<UserRepository>();
|
||||
final userInfo = await userRepo.getMyUser(service.professionalId);
|
||||
|
||||
final professionalRepo = FirebaseProfessionalRepository();
|
||||
final professionalRepo = Injector.appInstance.get<ApiProfessionalRepository>();
|
||||
final professionalInfo =
|
||||
await professionalRepo.getProInfo(service.professionalId);
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
const String _baseUrl = 'https://backend.prosapp.co/api/v1';
|
||||
|
||||
class ApiException implements Exception {
|
||||
final int statusCode;
|
||||
final String message;
|
||||
ApiException(this.statusCode, this.message);
|
||||
@override
|
||||
String toString() => 'ApiException($statusCode): $message';
|
||||
}
|
||||
|
||||
class ApiService {
|
||||
static ApiService? _instance;
|
||||
static ApiService get instance => _instance ??= ApiService._();
|
||||
ApiService._();
|
||||
|
||||
String? _token;
|
||||
|
||||
Future<String?> getToken() async {
|
||||
if (_token != null) return _token;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
_token = prefs.getString('token');
|
||||
return _token;
|
||||
}
|
||||
|
||||
Future<void> saveToken(String token) async {
|
||||
_token = token;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('token', token);
|
||||
}
|
||||
|
||||
Future<void> clearToken() async {
|
||||
_token = null;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove('token');
|
||||
}
|
||||
|
||||
Future<Map<String, String>> _headers({bool auth = true}) async {
|
||||
final headers = <String, String>{'Content-Type': 'application/json'};
|
||||
if (auth) {
|
||||
final token = await getToken();
|
||||
if (token != null) headers['Authorization'] = 'Bearer $token';
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
dynamic _parse(http.Response res) {
|
||||
final body = jsonDecode(res.body);
|
||||
if (res.statusCode >= 200 && res.statusCode < 300) return body;
|
||||
final msg = body is Map ? (body['message'] ?? res.reasonPhrase) : res.reasonPhrase;
|
||||
throw ApiException(res.statusCode, msg.toString());
|
||||
}
|
||||
|
||||
Future<dynamic> get(String path, {bool auth = true, Map<String, String>? query}) async {
|
||||
final uri = Uri.parse('$_baseUrl$path').replace(queryParameters: query);
|
||||
final res = await http.get(uri, headers: await _headers(auth: auth));
|
||||
return _parse(res);
|
||||
}
|
||||
|
||||
Future<dynamic> post(String path, Map<String, dynamic> body, {bool auth = false}) async {
|
||||
final res = await http.post(
|
||||
Uri.parse('$_baseUrl$path'),
|
||||
headers: await _headers(auth: auth),
|
||||
body: jsonEncode(body),
|
||||
);
|
||||
return _parse(res);
|
||||
}
|
||||
|
||||
Future<dynamic> patch(String path, Map<String, dynamic> body, {bool auth = true}) async {
|
||||
final res = await http.patch(
|
||||
Uri.parse('$_baseUrl$path'),
|
||||
headers: await _headers(auth: auth),
|
||||
body: jsonEncode(body),
|
||||
);
|
||||
return _parse(res);
|
||||
}
|
||||
|
||||
Future<String> uploadFile(String filePath) 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(await http.MultipartFile.fromPath('file', filePath));
|
||||
final streamed = await req.send();
|
||||
final res = await http.Response.fromStream(streamed);
|
||||
final body = jsonDecode(res.body);
|
||||
if (res.statusCode >= 200 && res.statusCode < 300) return body['url'] as String;
|
||||
throw ApiException(res.statusCode, body['message']?.toString() ?? 'Upload failed');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user