diff --git a/.gitignore b/.gitignore index 8b26114..e0f0436 100644 --- a/.gitignore +++ b/.gitignore @@ -118,3 +118,5 @@ app.*.symbols !**/ios/**/default.perspectivev3 !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages !/dev/ci/**/Gemfile.lock + +firebase-credentials.json \ No newline at end of file diff --git a/aplicacion_hack/android/settings.gradle.kts b/aplicacion_hack/android/settings.gradle.kts index c21f0c5..5ea2823 100644 --- a/aplicacion_hack/android/settings.gradle.kts +++ b/aplicacion_hack/android/settings.gradle.kts @@ -20,6 +20,9 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" id("com.android.application") version "9.0.1" apply false + // START: FlutterFire Configuration + id("com.google.gms.google-services") version("4.3.15") apply false + // END: FlutterFire Configuration id("org.jetbrains.kotlin.android") version "2.3.20" apply false } diff --git a/aplicacion_hack/firebase.exe b/aplicacion_hack/firebase.exe deleted file mode 100644 index 8939ef9..0000000 Binary files a/aplicacion_hack/firebase.exe and /dev/null differ diff --git a/aplicacion_hack/firebase.json b/aplicacion_hack/firebase.json new file mode 100644 index 0000000..b44d29b --- /dev/null +++ b/aplicacion_hack/firebase.json @@ -0,0 +1 @@ +{"flutter":{"platforms":{"android":{"default":{"projectId":"hackon-58b23","appId":"1:338042609701:android:0f0f92d7f895794f371fcc","fileOutput":"android/app/google-services.json"}},"dart":{"lib/firebase_options.dart":{"projectId":"hackon-58b23","configurations":{"android":"1:338042609701:android:0f0f92d7f895794f371fcc","ios":"1:338042609701:ios:d1ac418d368d1df5371fcc","macos":"1:338042609701:ios:d1ac418d368d1df5371fcc","web":"1:338042609701:web:5f0a245f364e7604371fcc","windows":"1:338042609701:web:b01c28c419fddd25371fcc"}}}}}} \ No newline at end of file diff --git a/aplicacion_hack/lib/firebase_options.dart b/aplicacion_hack/lib/firebase_options.dart new file mode 100644 index 0000000..908492c --- /dev/null +++ b/aplicacion_hack/lib/firebase_options.dart @@ -0,0 +1,88 @@ +// File generated by FlutterFire CLI. +// ignore_for_file: type=lint +import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; +import 'package:flutter/foundation.dart' + show defaultTargetPlatform, kIsWeb, TargetPlatform; + +/// Default [FirebaseOptions] for use with your Firebase apps. +/// +/// Example: +/// ```dart +/// import 'firebase_options.dart'; +/// // ... +/// await Firebase.initializeApp( +/// options: DefaultFirebaseOptions.currentPlatform, +/// ); +/// ``` +class DefaultFirebaseOptions { + static FirebaseOptions get currentPlatform { + if (kIsWeb) { + return web; + } + switch (defaultTargetPlatform) { + case TargetPlatform.android: + return android; + case TargetPlatform.iOS: + return ios; + case TargetPlatform.macOS: + return macos; + case TargetPlatform.windows: + return windows; + case TargetPlatform.linux: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for linux - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + default: + throw UnsupportedError( + 'DefaultFirebaseOptions are not supported for this platform.', + ); + } + } + + static const FirebaseOptions web = FirebaseOptions( + apiKey: 'AIzaSyDfpYR_--oRlGdTjLnAZY6z3RLh3LLz5gk', + appId: '1:338042609701:web:5f0a245f364e7604371fcc', + messagingSenderId: '338042609701', + projectId: 'hackon-58b23', + authDomain: 'hackon-58b23.firebaseapp.com', + storageBucket: 'hackon-58b23.firebasestorage.app', + measurementId: 'G-TBT47P2HX5', + ); + + static const FirebaseOptions android = FirebaseOptions( + apiKey: 'AIzaSyBuT70SbADLeg92ll8keCySI8I4eYyqyLw', + appId: '1:338042609701:android:0f0f92d7f895794f371fcc', + messagingSenderId: '338042609701', + projectId: 'hackon-58b23', + storageBucket: 'hackon-58b23.firebasestorage.app', + ); + + static const FirebaseOptions ios = FirebaseOptions( + apiKey: 'AIzaSyAB7czRjHfrkHEjiDOvPLiUz9zS1UGiZbw', + appId: '1:338042609701:ios:d1ac418d368d1df5371fcc', + messagingSenderId: '338042609701', + projectId: 'hackon-58b23', + storageBucket: 'hackon-58b23.firebasestorage.app', + iosBundleId: 'com.example.aplicacionHack', + ); + + static const FirebaseOptions macos = FirebaseOptions( + apiKey: 'AIzaSyAB7czRjHfrkHEjiDOvPLiUz9zS1UGiZbw', + appId: '1:338042609701:ios:d1ac418d368d1df5371fcc', + messagingSenderId: '338042609701', + projectId: 'hackon-58b23', + storageBucket: 'hackon-58b23.firebasestorage.app', + iosBundleId: 'com.example.aplicacionHack', + ); + + static const FirebaseOptions windows = FirebaseOptions( + apiKey: 'AIzaSyDfpYR_--oRlGdTjLnAZY6z3RLh3LLz5gk', + appId: '1:338042609701:web:b01c28c419fddd25371fcc', + messagingSenderId: '338042609701', + projectId: 'hackon-58b23', + authDomain: 'hackon-58b23.firebaseapp.com', + storageBucket: 'hackon-58b23.firebasestorage.app', + measurementId: 'G-DYGG6KBJ6C', + ); +} diff --git a/aplicacion_hack/lib/main.dart b/aplicacion_hack/lib/main.dart index ab9a238..afea2b5 100644 --- a/aplicacion_hack/lib/main.dart +++ b/aplicacion_hack/lib/main.dart @@ -17,7 +17,7 @@ import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'screens/login_screen.dart'; import 'screens/home_screen.dart'; - +import 'firebase_options.dart'; // Opcional si usas FlutterFire CLI para generar opciones // ---------------------------------------------------------------- // HANDLER DE MENSAJES EN BACKGROUND // @@ -29,7 +29,7 @@ import 'screens/home_screen.dart'; Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { // IMPORTANTE: Si el handler hace operaciones async pesadas, // también hay que inicializar Firebase aquí. - await Firebase.initializeApp(); + await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); debugPrint('📬 [Background] Mensaje recibido: ${message.messageId}'); // TODO: Aquí puedes guardar el mensaje en local storage para mostrarlo // después cuando el usuario abra la app. diff --git a/aplicacion_hack/lib/screens/home_screen.dart b/aplicacion_hack/lib/screens/home_screen.dart index 063153c..5f65e23 100644 --- a/aplicacion_hack/lib/screens/home_screen.dart +++ b/aplicacion_hack/lib/screens/home_screen.dart @@ -24,7 +24,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; // Descomenta cuando Firebase esté configurado: -// import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import '../services/api_service.dart'; class HomeScreen extends StatefulWidget { @@ -89,7 +89,7 @@ class _HomeScreenState extends State _usuarioId = args; _cargarETA(); _iniciarAutoRefresh(); - // _registrarFCMToken(); // Activar cuando Firebase esté listo + _registrarFCMToken(); // Activar cuando Firebase esté listo } else { // Fallback: leer de shared_preferences si no viene por argumento _cargarUsuarioDeStorage(); @@ -179,43 +179,41 @@ class _HomeScreenState extends State // manda al backend para poder recibir notificaciones push. // DESCOMENTA cuando tengas Firebase configurado. // ---------------------------------------------------------------- - // Future _registrarFCMToken() async { - // try { - // final messaging = FirebaseMessaging.instance; - // - // // Pedir permisos de notificación al usuario (iOS requiere esto) - // final settings = await messaging.requestPermission( - // alert: true, - // sound: true, - // badge: true, - // ); - // - // if (settings.authorizationStatus == AuthorizationStatus.authorized) { - // final token = await messaging.getToken(); - // if (token != null && _usuarioId != null) { - // await _apiService.registrarFcmToken(_usuarioId!, token); - // debugPrint('✅ FCM Token registrado: ${token.substring(0, 20)}...'); - // } - // } - // - // // Escuchar notificaciones cuando la app está en FOREGROUND - // FirebaseMessaging.onMessage.listen((RemoteMessage message) { - // if (message.notification != null && mounted) { - // ScaffoldMessenger.of(context).showSnackBar( - // SnackBar( - // content: Text('🚛 ${message.notification!.body}'), - // backgroundColor: Colors.green.shade700, - // duration: const Duration(seconds: 5), - // ), - // ); - // // Refrescar ETA al recibir notificación - // _cargarETA(); - // } - // }); - // } catch (e) { - // debugPrint('Error registrando FCM token: $e'); - // } - // } + Future _registrarFCMToken() async { + try { + final messaging = FirebaseMessaging.instance; + + // Pedir permisos de notificación al usuario (iOS requiere esto) + final settings = await messaging.requestPermission( + alert: true, + sound: true, + badge: true, + ); + if (settings.authorizationStatus == AuthorizationStatus.authorized) { + final token = await messaging.getToken(); + if (token != null && _usuarioId != null) { + await _apiService.registrarFcmToken(_usuarioId!, token); + debugPrint('✅ FCM Token registrado: ${token.substring(0, 20)}...'); + } + } + // Escuchar notificaciones cuando la app está en FOREGROUND + FirebaseMessaging.onMessage.listen((RemoteMessage message) { + if (message.notification != null && mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('🚛 ${message.notification!.body}'), + backgroundColor: Colors.green.shade700, + duration: const Duration(seconds: 5), + ), + ); + // Refrescar ETA al recibir notificación + _cargarETA(); + } + }); + } catch (e) { + debugPrint('Error registrando FCM token: $e'); + } + } // ---------------------------------------------------------------- // CERRAR SESIÓN diff --git a/backend/hackathon.db b/backend/hackathon.db index b5a7c63..51abf3b 100644 Binary files a/backend/hackathon.db and b/backend/hackathon.db differ diff --git a/backend/main.py b/backend/main.py index d4868cc..c3624f3 100644 --- a/backend/main.py +++ b/backend/main.py @@ -140,16 +140,15 @@ TIPOS_EVENTO_VALIDOS = ["en_camino", "llegando", "completado", "retrasado"] import firebase_admin from firebase_admin import credentials, messaging -# --- DESCOMENTA ESTO CUANDO TENGAS EL ARCHIVO DE CREDENCIALES --- -# try: -# cred = credentials.Certificate("firebase-credentials.json") -# firebase_admin.initialize_app(cred) -# logger.info("✅ Firebase Admin SDK inicializado correctamente") -# except Exception as e: -# logger.error(f"❌ Error inicializando Firebase: {e}") -# --------------------------------------------------------------- +try: + cred = credentials.Certificate("firebase-credentials.json") + firebase_admin.initialize_app(cred) + logger.info("✅ Firebase Admin SDK inicializado correctamente") +except Exception as e: + logger.error(f"❌ Error inicializando Firebase: {e}") -FIREBASE_ACTIVO = False # Cambia a True al desbloquear Firebase + +FIREBASE_ACTIVO = True # Cambia a True al desbloquear Firebase # ===============================================================